- How many types of thread?
- How to specify the code to run on a thread
- How to manage multi-thread?
- How threads communicate?
- What matter if multithread access an instance?
4. How threads communicate?
Thread communicate via… hold up, wait a moment. I think we should recommend thread a bit more.
Questions here:
— How to send data from the task to objects running on the user interface (UI) thread?
— How allows your tasks to do background work and then move the results to UI elements such as bitmaps?
Now, we have some hint:
(1)— Every app has its own special thread that runs UI objects such as View
objects; this thread is called the UI thread. Besides, only objects running on the UI thread have access to other objects on that thread.
(2) — Tasks that you run on a thread from a thread pool aren’t running on your UI thread, so they don’t have access to UI objects.
(3)— ‘Handler’, you not only create a Handler
for a new thread, but also create another one connected to an existing thread too. When you connect a ‘Handler’ to your UI thread, the code that runs on the UI thread.
From (1), (2) and (3), we can prove is: to move data from a background thread to the UI thread, we can use a Handler
that’s running on the UI thread.
Not enough, it’s just a short story, now we have to know how they can communicate. This is a short quote from android’s document.
To move data from a task object running on a background thread to an object on the UI thread, start by storing references to the data and the UI object in the task object. Next, pass the task object and a status code to the object that instantiated the
Handler
. In this object, send aMessage
containing the status and the task object to theHandler
. BecauseHandler
is running on the UI thread, it can move the data to the UI object.
Follow documentation, we need 3 actions to send data from background thread to UI thread:
— Store data in the task object.
— Send status up the object hierarchy.
— Move data to the UI.
I make an example app to test this theory. I’ll create an imageview programmatically from background thread and load it to UI.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_thread_learning);
ImageView imv = new ImageView(getBaseContext());
imv.setImageResource(R.drawable.ic_launcher_background);
imv.setLayoutParams(new LinearLayout.LayoutParams(200, 200));
imv.setPadding(20, 20, 20, 20);
((LinearLayout) findViewById(R.id.rootLayout)).addView(imv);
}
We won’t use code above, because it’s just an easy way. We need to try hard to create view from background-thread and bring it to UI thread. LOL.
public class ThreadLearningActivity extends AppCompatActivity {
LinearLayout rootLayout;
Handler mHandler;
Thread mThread;
private Bundle bb = new Bundle();
ImageView imv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_thread_learning);
imv = new ImageView(getBaseContext());
((LinearLayout) findViewById(R.id.rootLayout)).addView(imv);
mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
bb = msg.getData();
int str = bb.getInt("img");
imv.setImageResource(str);
System.out.println(str);
}
};
mThread = new Thread(new MyRunnable(mHandler));
//I pass Runnable object in thread so that the code inside the run() method
//of Runnable object gets executed when I start my thread here. But the code executes in new thread
mThread.start(); //thread started
}
}
class MyRunnable implements Runnable {
private Handler mHandler;
public MyRunnable(Handler h) {
this.mHandler = h;
}
@Override
public void run() {
// Moves the current Thread into the background
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
Message m = Message.obtain(); //get null message
Bundle b = new Bundle();
//I use this way to fake feature download image, which take time to work in background
b.putInt("img", R.drawable.ic_launcher_background);
m.setData(b);
//use the handler to send message
mHandler.sendMessage(m);
}
}
You can pass anything from the parameters if you don’t want to use static concepts. In the above codes, I have implemented two classes. I used the common handler in both thread classes. I pass handler h1 as the parameters of Runnable object and start() method there to trigger the run() method of another thread class. The thread which contains run() method is the UI (Main) thread.
We must use UI thread to update UI. Worker (Background) threads can’t do UI update. The communication between worker thread with UI is done via handler.
So, I define handler h2 in UI thread class. When UI thread class constructor is called from background thread class, I get my h2 values from h1 that come from the constructor. And I use h2 for my communication. In fact, h2 and h1 belong to the same memory space in the system.
Note: when thread.start() happens, it triggers the run of the Runnable class, it creates a separate thread. So every time, you call start(), there is a new thread with the same priority of callee thread.
5. What matter if multithread access an instance?
I still don’t research finish this question… Please take a cup coffee and think it 😛
No responses yet