There are many examples on the Internet about how to use Handler to execute code execution in a UI stream. But I can not find the opposite example - when data is transferred through Handler for processing to a separate stream. I am sure that this is possible to implement, but I can not figure out exactly how this can be done.

Maybe someone can write a code diagram for such a data handler? Thank.

  • That is, for example, the launch of a new AsyncTask from Handler ? - VAndrJ
  • This is the obvious option. But here, as I understand it, when the next portion of data is received, a situation may arise when two portions are processed in parallel. I need a sequential queue of processing. - UncleAndy
  • So just run on Executor e: .executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); - VAndrJ pm
  • The variant with executeOnExecutor , in general, solves the problem. But the fact is that I would like to get a solution at the level of Handler and Task . In the test task such a task came across and it was one of the complaints. - UncleAndy
  • Strange claim of course. Alternatively, you can organize such a scheme: the data is transmitted to the Handler , in which there is a check whether there is a working thread (boolean flag, for example). If not, a stream is started and a flag is set. Until the flag is cleared, new data / tasks are saved for execution. When a separate thread has finished processing, it sends to the Handler about its ending, the flag is reset, the first data is taken from the saved data and sent to the stream. Well, it will be in a circle. - VAndrJ

1 answer 1

HandlerThread is very suitable for this.

Here's a really working code ...

First the class itself. Data sets are sent to it for updating via ContentProvider :

 public class UpdateDataThread { Handler h; HandlerThread ht; ContentResolver contentResolver; public UpdateDataThread(ContentResolver cr) { contentResolver = cr; ht = new HandlerThread("UpdateDataThread"); ht.start(); Handler.Callback callback = new Handler.Callback() { @Override public boolean handleMessage(Message msg) { ArrayList<DataRow> data = (ArrayList<DataRow>) msg.obj; updateDataInThread(data); return false; } }; h = new Handler(ht.getLooper(), callback); } public void updateData(ArrayList<DataRow> data) { Message msg = new Message(); msg.obj = data; h.sendMessage(msg); } public void close() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { ht.quitSafely(); } else { ht.quit(); } } private void updateDataInThread(ArrayList<DataRow> data) { ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>(); ContentValues cv = new ContentValues(); for (DataRow row: data) { cv.clear(); if (row._next != null) { cv.put("next_id", row._next.id); } else { cv.putNull("next_id"); } ops.add(ContentProviderOperation.newUpdate(Uri.parse("content://"+ListDataProvider.DOMAIN+"/rows")) .withSelection("id = ?", new String[]{row.id.toString()}) .withValues(cv) .build()); } try { contentResolver.applyBatch(ListDataProvider.DOMAIN, ops); } catch (RemoteException e) { e.printStackTrace(); } catch (OperationApplicationException e) { e.printStackTrace(); } } } 

In the main code, a constantly present UpdateDataThread instance is created and, as the application updateData(...) data is sent to it via the updateData(...) call of this instance. Because in reality, a Message is being sent, and for one Handler they are lined up, as I understand, they will be processed sequentially. As required.