android-non-ui-ui-thread-communications-part-5-5
This is the last post in my series regarding Android thread communications. Parts 1 through 4 are linked in below.
In this series, I have so far outlined four different approaches for how Android non-user interface threads can communicate user interface (UI) updates back to the UI thread. As you have learned in this series, new threads to perform longer running work is the way to build applications and to avoid Android Not Responsive popups, but if those non-UI threads try to update UI components (like putting new String data in a TextView widget) they trigger a CalledFromWrongThreadException. Previous posts have used the Activity’s runOnUiThread() method, a View’s post() method, the Handler Framework, and Broadcast/BroadcastReceiver components to handle non-UI to UI thread communications. In this last post, my favorite option – the AsyncTask – is explored.
THE SIMPLE APP REVIEW
As reminder or note to those looking at these posts out of sequennce, throughout this series, I have used the same simple application (called Simple App) to demonstrate each communication option. The Simple App has two buttons to start/stop a non-UI thread. The non-UI thread’s job is to simulate long running work by generating a random number, then call the UI to have a TextView widget update the display of the random number, and then sleep for a number of seconds.
The SimpleApp example code for demonstrating option #5 can be found here(in an Eclipse project ZIP file).
ASYNCTASK
The AsyncTask is a special Android convenience class for creating a new Thread that can “publish results on the UI thread without having to manipulate threads and/or handlers.” That last quote is directly from the AsyncTask class documentationin the Android reference guide. In other words, the AsyncTask was explicitly built to provide Android developers with an easy way to create threads that have a direct communication channel back to the UI thread.
In order to create an AsynTask, developers must extend the abstract AsyncTask super class and then implement the methods below.
- doInBackground() – code here is executed on a new, non-UI thread that Android creates when the AsynTask is executed. This is the only required method of an AsyncTask subclass.
- onPreExecute() – code executed on the UI thread by Android before non-UI thread work is executed in doInBackground() code.
- onPostExecute() – code executed on the UI thread by Android after non-UI thread work is executed in doInBackground.
- onProgressUpdate – called on the UI thread by Android whenever publishProgress(Progress…) is called (typically in the doInBackground method) to provide the user interface (and user) with updates while the separate thread is still running.
Notice that three of four methods of the AsyncTask run on the UI thread. The only method that runs in a non-UI thread is doInBackground(). So you can see the AsyncTask was really built to provide that non-UI to UI communications.
To exemplify AsyncTask’s capability, I created an inner class for the AsyncTask (called DoSomethingTask) to compute the random number and return the results to the UI. Here is the code (again – it can be pulled from the Eclipse download referenced above).
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
public class DoSomethingTask extends AsyncTask<Void, String, Void> {
private static final String TAG = "DoSomethingTask";
private static final int DELAY = 5000; // 5 seconds
private static final int RANDOM_MULTIPLIER = 10;
@Override
protected void onPreExecute() {
Log.v(TAG, "starting the Random Number Task");
super.onPreExecute();
}
@Override
protected void onProgressUpdate(String... values) {
Log.v(TAG, "reporting back from the Random Number Task");
updateResults(values[0].toString());
super.onProgressUpdate(values);
}
@Override
protected void onCancelled(Void result) {
Log.v(TAG, "cancelled the Random Number Task");
super.onCancelled(result);
}
@Override
protected Void doInBackground(Void... params) {
Log.v(TAG, "doing work in Random Number Task");
String text="";
while (true) {
if (isCancelled()) {
break;
}
int randNum = (int) (Math.random() * RANDOM_MULTIPLIER);
text = String.format(getString(R.string.service_msg), randNum);
publishProgress(text);
try {
Thread.sleep(DELAY);
} catch (InterruptedException e) {
Log.v(TAG, "Interrupting the Random Number Task");
}
}
return null;
}
}
|
Note the random number generation (as well as the thread sleeping) occurs in the doInBackground() method – again to simulate long running, continuous work that is often accomplished in a background thread. Also note that the doInBackground() method calls postProgress() with new String data after it has generated a random number and wants to send this data back to the UI thread.
DoSomethingTask extends AsyncTask and has three generic types. The first, which in this example is Void, defines the input parameter type. This simple task takes no input from the UI to generate a random number. Your background work may need some information from the UI side to get it working and this parameter specifies the type of information being supplied. This type defines the input parameter type for the doInBackground() method.
The second AsyncTask generic type provided, which is a String here, is the type of data passed to the onProgressUpdate() method in publishProgess() calls made from doInBackground(). Here, the new random number generated by doInBackground() is passed back to the UI thread in order to update the display by passing the random number as String text to the onProgressUpdate() call.
The last generic type to AsyncTask subclasses is the return type of the doInBackground() work. In this case, the doInBackground() method does not return anything back to the UI thread (except through onProgressUpdate) so the third type is also Void. Again, your non-UI threads may wish to return some information back to the thread’s creator and this is the type of information passed back.
With this AsyncTask in place, the UI – namely the owning Activity that drives the application – can create an instance of the AsyncTask (DoSomethingTask) and have its background work begin by calling execute. This work is accomplished in the startGenerating() method (below) which I have setup to be called by an onClickListener waiting for the Start button to be pushed.
|
1
2
3
4
|
private void startGenerating() {
randomWork = new DoSomethingTask();
randomWork.execute();
}
|
Finally, the AsyncTask calls the Activity’s updateResult() method (below) from the onProgressUpdate() method when a new random number is generated and the UI TextView displaying the number needs to be updated. Again, this is possible because the onProgressUpdate() method runs on the UI thread.
|
1
2
3
|
public void updateResults (String results){
mainFrag.getResultsTextView().setText(results);
}
|
Note additional cleanup methods are provided in the code to stop the AsyncTask when the Stop button is pushed. It should also be noted that this example was kept simple for demonstration sake. Therefore, it has some faults you would want to correct in a real app situation. For example, you might want to make sure only one AsyncTask is ever created (right now you could create many by clicking on Start many times).
CONSIDERATIONS OF OPTION 5 – ASYNCTASK
The AsyncTask is a real convenience for Android developers in that it allows them to accomplish multithreading without having to think about all the communications across threads and without having to think about Runnables, Thread instances, special methods to call, queues, etc. to get the work done. The convenience of the three UI-thread methods makes getting information across the thread boundry real easy. However, the AsyncTask is fairly basic and when more complex multithreading needs arise, it may be too simple to use. In fact, the documentation is pretty clear about when to use AsyncTask and when to move to something like classes available in Java’s concurrent package.
AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent pacakge such as Executor, ThreadPoolExecutor and FutureTask.
While in this example, the AsyncTask was built as inner class to the Activity, the AsyncTask can be a completely separate class with no ties to the Activity or other UI component. This allows the non-UI threads to be completely decoupled from the UI.
WRAP UP
So I hope on your next Android project, you’ll remember that you have lots of options for thread communications when it comes time to move background work to a separate non-UI thread. Namely, you can:
- Use runOnUiThread( ) method call
- Use post( ) method call
- Use the Handler framework
- Use a Broadcasts and BroadcastReceiver (optionally with LocalBroadcastManager)
- Use an AsyncTask’s onProgressUpdate( ) method
Good Android developers know it is important to use separate threads to avoid ANR. The trick is sometimes figuring out how to get those threads communicating without creating other problems like CalledFromWrongThreadException. Now you are armed with an understanding of thread communication options and considerations for making the best decision for your application needs.
Allow Intertechto help guide you through other mobile development technology issues and considerations. If you need training in Android, iOS or other mobile development platform, please checkout our mobile program. Or, contact our consulting departmentif you need some help on your mobile project. We are the home of instructors that consult and consultants that teach.
Read more: http://www.intertech.com/Blog/android-non-ui-ui-thread-communications-part-5-5/#ixzz3Myv7NG4l
Follow us: @IntertechInc on Twitter | Intertech on Facebook
android-non-ui-ui-thread-communications-part-5-5的更多相关文章
- Android Non-UI to UI Thread Communications(Part 3 of 5)
Original:http://www.intertech.com/Blog/android-non-ui-to-ui-thread-communications-part-3-of-5/ Conti ...
- Android Non-UI to UI Thread Communications(Part 2 of 5)
Original:http://www.intertech.com/Blog/android-non-ui-to-ui-thread-communications-part-2-of-5/ his i ...
- Android异步更新UI的四种方式
Android异步更新UI的四种方式 2015-09-06 09:23 segmentfault 字号:T | T 大家都知道由于性能要求,android要求只能在UI线程中更新UI,要想在其他线程中 ...
- Android开发之UI更新交互机制与实例解析
android开发过程中,经常需要更新UI的状态和文案等.这是就需要对UI进行 更新.在android中更新UI一般有三种方法,handler机制.RunOnUiThread方法以及AsyncTask ...
- Android开发 ---基本UI组件7 :分页功能、适配器、滚动条监听事件
效果图: 1.activity_main.xml 描述: 定义了一个按钮 <?xml version="1.0" encoding="utf-8"?> ...
- Android开发 ---基本UI组件4:拖动事件、评分进度条、圆圈式进度条、进度条控制
Android开发 ---基本UI组件4 1.activity_main.xml 描述: 定义了一个按钮 <?xml version="1.0" encoding=" ...
- android线程控制UI更新(Handler 、post()、postDelayed()、postAtTime)
依照以下的理解就是handler与ui线程有一定的关联能够由于更新界面仅仅能在主线程中全部更新界面的地方能够在接受消息的handleMessage那里还有更新界面能够在handler.port(new ...
- Android多线程更新UI的方式
Android下,对于耗时的操作要放到子线程中,要不然会残生ANR,本次我们就来学习一下Android多线程更新UI的方式. 首先我们来认识一下anr: anr:application not rep ...
- ReactNative Android之原生UI组件动态addView不显示问题解决
ReactNative Android之原生UI组件动态addView不显示问题解决 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请表明出处:http://www.cnblogs.com ...
- Android开发 ---基本UI组件6 :只定义一个listView组件,然后通过BaseAdapter适配器根据数据的多少自行添加多个ListView显示数据
效果图: 1.activity_main.xml 描述: 定义了一个按钮 <?xml version="1.0" encoding="utf-8"?> ...
随机推荐
- ASP.NET分页
[代码][C#]代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ...
- NPOI导出word,以及对table的一些设置
参考网址:http://www.aiuxian.com/article/p-1970779.html NPOI版本:2.1.3.1 最终效果图: 代码: /// <summary> /// ...
- 49.关于Quartus和ISE中ROM的初始化和仿真的一些小结
最近在玩Altera的FPGA,当我用Quartus II自带的IP核生成ROM时,出现了各种问题,于是在网上各种查资料,终于解决了我的问题.这里做一下小结,方便自己日后查阅. Quartus II ...
- java无符号移位(>>>)和有符号移位(>>)
java中>>(<<)表示有符号的移位.<<<(>>>)表示无符号移位 如: int num = 22; 二进制是0001 0110, nu ...
- 软件工程结对开发——返回一个整数数组中最大子数组的和(JAVA)
题目:返回一个整数数组中最大子数组的和. 要求: 输入一个整型数组,数组里有正数也有负数: 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和: 求所有子数组的和的最大值.要求时间复杂度为 ...
- php调用微信发送自定义模版接口
function sendWechatmodel($openid,$data,$go_url)//接受消息的用户openid,发送的消息,点击详情跳转的url { ...
- Android 上传图片到 Asp.Net 服务器的问题
最近在做一个手机app联合系统管理做的应用程序,管理程序管理数据的发布和增删改查,手机app负责显示和操作业务逻辑这么一个功能. 刚开始路走的都很顺,但是走到通过Android客户端上传图片到Asp. ...
- 一些常用到的Centos命令
CentOS常用命令在我们的使用中,经常被使用.所以,我们对一些经常使用又很重要的CentOS常用命令进行了全面的整理.下面,就来介绍这些CentOS常用命令. 一:使用CentOS常用命令查看cpu ...
- Careercup - Google面试题 - 6407924087783424
2014-05-07 15:17 题目链接 原题: Given an array of n elements (a1,a2,..ai,...,an). You are allow to chose a ...
- 好书推荐——《Soft Skill》
这本书不是一本简单的叙述程序员职业规划和如何提高能力的书. 他论述了如何做一个高产,快乐,幸福的程序员,包括职业生涯,理财,学习,健身,信仰等各个方面的内容. 推荐给每一位伟大的拯救宇宙的程序员! 书 ...