Suppose there is a String. It needs to be broken down into characters and each character separately with a slight delay between characters displayed on the screen in a parallel stream. That is, you need to achieve the effect of printing text.

The following code is written by a programmer by profession, but it does not work correctly. How to work with it or how to correct it in order to achieve the above result?

import java.util.Timer; ..... private final Handler mHandler = new Handler(); private Timer mTimer = new Timer(); private TextView tv3; .... class Task extends TimerTask { private string mData; private int k; public Task(String data){ mData = data; k=1; } public void run() { //Данный код выполяется каждые 5 секунд if(k<mData.length()){ handler.post(new Runnable(){ public void run() { //Вывод строки tv3.setText(mData.substring(0, k)); k++; } }); } else{ mTimer.cancel(); } } } ....Конструтор Activity{ .... tv3 = (TextView)findViewById(R.id.tv3); mTimer = new Timer(); //5000 - 5 секунд, str - строка для вывода String str = "Строчка"; mTimer.schedule(new Task(str), 5000); } 
  • To display? - post_zeew
  • Yes. In TextView, for example. - FullyRetarded
  • one
    Directly from the parallel stream to display on the screen will not work, since only one main stream has access to the UI. - post_zeew
  • Then you need to return the data to the main thread, which would update the UI, and then again pass control to the parallel thread so that it delays the next character to the main one, and so on until the end of the data. I remembered the threads because if you do all this in the main thread, the UI will hang because of Thread.Sleep (). If there is a method that does not stop the execution of the process, but simply counts the time, then the second thread is not needed here at all. - FullyRetarded
  • The elementary problem. In the most primitive case, you can use the same AsyncTask . - post_zeew

1 answer 1

You can use broadcast messages to update the UI from different streams. In AsyncTask, in the onPostExecute method, you must send the data, and in the Activity you create an internal class that extends BroadcastReceiver.

 //AsyncTask @Override protected void onPostExecute(JSONArray result) { super.onPostExecute(result); if(result!=null&&result.length()>0){ for (int i = 0; i < result.length(); i++) { try { JSONObject explrObject = result.getJSONObject(i); String text1 = explrObject.getString("text1"); String text2= explrObject.getString("text1"); Intent broadcastIntent = new Intent(); broadcastIntent.setAction("PROCESS_RESPONSE"); broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT); broadcastIntent.putExtra("text1", text1); broadcastIntent.putExtra("text2", text2); context.sendBroadcast(broadcastIntent); } catch (JSONException e) { e.printStackTrace(); } } } } 

In it, in the onReceive method, you accept this message and update the UI. You also need to register the BroadcastReceiver in the onCreate method.

 // MainActivity @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Register receiver IntentFilter filter = new IntentFilter(RequestReceiver.PROCESS_RESPONSE); filter.addCategory(Intent.CATEGORY_DEFAULT); receiver = new RequestReceiver(); registerReceiver(receiver, filter); } class RequestReceiver extends BroadcastReceiver { public static final String PROCESS_RESPONSE = "PROCESS_RESPONSE"; @Override public void onReceive(Context context, Intent intent) { String text1 = intent.getStringExtra("text1"); String text2 = intent.getStringExtra("text2"); updateUI(text1, text2); } } private void updateUI(String text1, String text2) { TextView textView1 = (TextView) findViewById(R.id.textView1); textView1.setText(text1); TextView textView2 = (TextView) findViewById(R.id.textView2); textView1.setText(text2); } 

Example in documentation: https://developer.android.com/training/run-background-service/report-status.html