0
点赞
收藏
分享

微信扫一扫

Android线程的学习 之二

月白色的大狒 2023-07-31 阅读 56


在网上有很多文章讲述主线程和其他子线程如何交互,传送信息,最终谁来执行处理信息之类的,个人理解是最简单的方法——判断Handler对象里面的Looper对象是属于哪条线程的,则由该线程来执行!

   1. 当Handler对象的构造函数的参数为空,则为当前所在线程的Looper;



   2. Looper.getMainLooper()得到的是主线程的Looper对象,Looper.myLooper()得到的是当前线程的Looper对象。



现在来看一个例子,模拟从网络获取数据,加载到ListView的过程:

1. public class ListProgressDemo extends ListActivity { 
2. 
3.    @Override 
4.    public void onCreate(Bundle savedInstanceState) { 
5.        super.onCreate(savedInstanceState); 
6.        setContentView(R.layout.listprogress); 
7. 
8.        ((Button) findViewById(R.id.load_Handler)).setOnClickListener(new View.OnClickListener(){ 
9. 
10.            @Override 
11.            public void onClick(View view) { 
12.                data = null; 
13.                data = new ArrayList<String>(); 
14. 
15.                adapter = null; 
16. 
17.                showDialog(PROGRESS_DIALOG); 
18.                new ProgressThread(handler, data).start(); 
19.            } 
20.        }); 
21.    } 
22. 
23.    @Override 
24.    protected Dialog onCreateDialog(int id) { 
25.        switch(id) { 
26.        case PROGRESS_DIALOG: 
27.                 return ProgressDialog.show(this, "",  
28.                   "Loading. Please wait...", true); 
29. 
30.        default: return null; 
31.        } 
32.    } 
33. 
34.    private class ProgressThread extends Thread { 
35. 
36.        private Handler handler; 
37.        private ArrayList<String> data; 
38. 
39.        public ProgressThread(Handler handler, ArrayList<String> data) { 
40.            this.handler = handler; 
41.            this.data = data; 
42.        } 
43. 
44.        @Override 
45.        public void run() { 
46.            for (int i=0; i<8; i++) { 
47.                data.add("ListItem"); //后台数据处理
48.                try { 
49.                    Thread.sleep(100); 
50.                }catch(InterruptedException e) { 
51.                     
52.                    Message msg = handler.obtainMessage(); 
53.                    Bundle b = new Bundle(); 
54.                    b.putInt("state", STATE_ERROR); 
55.                    msg.setData(b); 
56.                    handler.sendMessage(msg);  
57.                     
58.                } 
59.            } 
60.            Message msg = handler.obtainMessage(); 
61.            Bundle b = new Bundle(); 
62.            b.putInt("state", STATE_FINISH); 
63.            msg.setData(b); 
64.            handler.sendMessage(msg); 
65.        } 
66.         
67.    } 
68. 
69.    // 此处甚至可以不需要设置Looper,因为Handler默认就使用当前线程的Looper
70.    private final Handler handler = new Handler(Looper.getMainLooper()) {
71. 
72.        public void handleMessage(Message msg) { // 处理Message,更新ListView
73.            int state = msg.getData().getInt("state"); 
74.            switch(state){ 
75.                case STATE_FINISH: 
76.                    dismissDialog(PROGRESS_DIALOG); 
77.                    Toast.makeText(getApplicationContext(), 
78.                            "加载完成!", 
79.                            Toast.LENGTH_LONG) 
80.                         .show(); 
81. 
82.                    adapter = new ArrayAdapter<String>(getApplicationContext(), 
83.                            android.R.layout.simple_list_item_1, 
84.                            data ); 
85.                             
86.                    setListAdapter(adapter); 
87. 
88.                    break; 
89. 
90.                case STATE_ERROR: 
91.                   dismissDialog(PROGRESS_DIALOG); 
92.                   Toast.makeText(getApplicationContext(), 
93.                           "处理过程发生错误!", 
94.                           Toast.LENGTH_LONG) 
95.                        .show(); 
96. 
97.                   adapter = new ArrayAdapter<String>(getApplicationContext(), 
98.                           android.R.layout.simple_list_item_1, 
99.                           data ); 
100.                            
101.                      setListAdapter(adapter); 
102. 
103.                      break; 
104. 
105.               default: 
106. 
107.            } 
108.        } 
109.    }; 
110. 
111. 
112.    private ArrayAdapter<String> adapter; 
113.    private ArrayList<String> data; 
114. 
115.    private static final int PROGRESS_DIALOG = 1; 
116.    private static final int STATE_FINISH = 1; 
117.    private static final int STATE_ERROR = -1; 
118. }

这个例子,我自己写完后觉得还是有点乱,要稍微整理才能看明白线程间交互的过程以及数据的前后变化。随后了解到AsyncTask类,相应修改后就很容易明白了!






2.3 AsyncTask


AsyncTask版: 
 
 
 
1. ((Button) findViewById(R.id.load_AsyncTask)).setOnClickListener(new View.OnClickListener(){ 
2. 
3.    @Override 
4.    public void onClick(View view) { 
5.        data = null; 
6.        data = new ArrayList<String>(); 
7. 
8.        adapter = null; 
9. 
10.        //显示ProgressDialog放到AsyncTask.onPreExecute()里 
11.        //showDialog(PROGRESS_DIALOG); 
12.        new ProgressTask().execute(data); 
13.    } 
14. }); 
15. 
16. private class ProgressTask extends AsyncTask<ArrayList<String>, Void, Integer> { 
17. 
18. 
19. @Override 
20. protected void onPreExecute() { 
21.    // 先显示ProgressDialog
22.    showDialog(PROGRESS_DIALOG); 
23. } 
24. 
25. 
26. @Override 
27. protected Integer doInBackground(ArrayList<String>... datas) { 
28.    ArrayList<String> data = datas[0]; 
29.    for (int i=0; i<8; i++) { 
30.        data.add("ListItem"); 
31.    } 
32.    return STATE_FINISH; 
33. } 
34. 
35. 
36. @Override 
37. protected void onPostExecute(Integer result) { 
38.    int state = result.intValue(); 
39.    switch(state){ 
40.    case STATE_FINISH: 
41.        dismissDialog(PROGRESS_DIALOG); 
42.        Toast.makeText(getApplicationContext(), 
43.                "加载完成!", 
44.                Toast.LENGTH_LONG) 
45.             .show(); 
46. 
47.        adapter = new ArrayAdapter<String>(getApplicationContext(), 
48.                android.R.layout.simple_list_item_1, 
49.                data ); 
50.                 
51.        setListAdapter(adapter); 
52. 
53.        break; 
54.         
55.    case STATE_ERROR: 
56.       dismissDialog(PROGRESS_DIALOG); 
57.       Toast.makeText(getApplicationContext(), 
58.               "处理过程发生错误!", 
59.               Toast.LENGTH_LONG) 
60.            .show();
61. 
62.       adapter = new ArrayAdapter<String>(getApplicationContext(), 
63.               android.R.layout.simple_list_item_1, 
64.               data );
65. 
66.          setListAdapter(adapter);
67. 
68.          break;
69. 
70.   default:
71. 
72.   }
73. }

   Android另外提供了一个工具类:AsyncTask。它使得UI thread的使用变得异常简单。它使创建需要与用户界面交互的长时间运行的任务变得更简单,不需要借助线程和Handler即可实现。



    1)   子类化AsyncTask



    2)   实现AsyncTask中定义的下面一个或几个方法



       



       



        onProgressUpdate(Progress...)   在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。



          onPostExecute(Result) 执行完成后的操作,传送结果给UI 线程。






       



        1) AsyncTask的实例必须在UI thread中创建;



        2) AsyncTask.execute方法必须在UI thread中调用;



       



    同时要注意:该task只能被执行一次,否则多次调用时将会出现异常。而且是不能手动停止的,这一点要注意,看是否符合你的需求!






    在使用过程中,发现AsyncTask的构造函数的参数设置需要看明白: AsyncTask<Params, Progress, Result>



    Params对应doInBackground(Params...)的参数类型。而new AsyncTask().execute(Params... params),就是传进来的Params数据,你可以execute(data)来传送一个数据,或者execute(data1, data2, data3)这样多个数据。



    Progress对应onProgressUpdate(Progress...)的参数类型;



    Result对应onPostExecute(Result)的参数类型。



    当以上的参数类型都不需要指明某个时,则使用Void,注意不是void。不明白的可以参考上面的例子,或者API Doc里面的例子。


举报

相关推荐

0 条评论