How to effectively update Android text ads?

I am working on an Android application that is facing performance issues. My goal is to get strings from AsyncTask and display them in a TextView. The TextView is initially empty, and each time another process sends a line, it combines it with the current contents of the text field. I am currently using StringBuilder to store the main string, and every time I get a new string, I add it to StringBuilder and call

myTextView.setText(myStringBuilder.toString()) 

The problem is that the background process can send up to 100 lines per second, and my method is not efficient enough.

Redrawing the entire TextView every time is obviously a bad idea (O (N²) time complexity), but I don't see another solution ...

Do you know an alternative to TextView that could do these concatenations in O (N)?

+4
source share
3 answers

I finally found the answer using hasxz and Greyson here, as well as the code here . When the lines appeared in the queues, I decided to update the interface every 100 ms. For the record here, what my code looks like:

 private static boolean output_upToDate = true; /* Handles the refresh */ private Handler outputUpdater = new Handler(); /* Adjust this value for your purpose */ public static final long REFRESH_INTERVAL = 100; // in milliseconds /* This object is used as a lock to avoid data loss in the last refresh */ private static final Object lock = new Object(); private Runnable outputUpdaterTask = new Runnable() { public void run() { // takes the lock synchronized(lock){ if(!output_upToDate){ // updates the outview outView.setText(new_text); // notifies that the output is up-to-date output_upToDate = true; } } outputUpdater.postDelayed(this, REFRESH_INTERVAL); } }; 

and I put this in my onCreate() method:

 outputUpdater.post(outputUpdaterTask); 

Some explanation: when my application calls its onCreate() method, my outputUpdater handler receives one request for updating. But this task ( outputUpdaterTask ) sets itself an update request 100 ms later. lock is shared with a process that sends newlines and sets output_upToDate to false.

+2
source

As long as there is a newline between the lines, you can use the ListView to add the lines and hold the lines themselves in an ArrayList or LinkedList to which you add when AsyncTask receives the lines.

You might also consider invalidating a TextField with a lower reputation; speak 10 times per second. This will certainly improve responsiveness. The following may work:

 static long lastTimeUpdated = 0; if( receivedString.size() > 0 ) { myStringBuilder.append( receivedString ); } if( (System.currentTimeMillis() - lastTimeUpdated) > 100 ) { myTextView.setText( myStringBuilder.getChars( 0, myStringBuilder.length() ); } 

If the lines get into packets - so that you have a delay between packets more than, say, a second, then reset the timer for each update that will run this code to restart to pick up the final part of the last packet.

+2
source

Try setting up the update. Therefore, instead of updating 100 times per second, like the speed of generation. Save 100 lines in the line builder and then update once per second.

The code should look like this:

 StringBuilder completeStr = new StringBuilder(); StringBuilder new100Str = new StringBuilder(); int counter = 0; if(counter < 100) { new100Str.append(newString); counter++; } else { counter = 0; completeStr.append(new100Str); new100Str = new StringBuilder(); myTextView.setText(completeStr.toString()); } 

NOTE. The code above is for illustrative purposes only, so you may need to modify it to suit your needs.

+1
source

Source: https://habr.com/ru/post/1386980/


All Articles