- 当应用启动,系统会创建一个主线程,也叫UI线程,系统对每个UI组件的调用事件都在UI线程中分发出去,而不会为每个UI单独建立线程,这种单线程模型有两个准则:
- 不要阻塞UI线程
- 不能在UI线程之外访问Android UI
- 下面方法可以将执行放在UI线程,但不常用
- Activity.runOnUiThread(Runnable)
- View.post(Runnable)
- View.postDelayed(Runnable, long)
- Handler类的主要作用:
- 在新启动的线程中发送消息,调用sendMessage系列函数
- 在主线程中获取,处理消息,当新线程发送消息时,主线程会回调handleMessage方法进行处理
HandlerHandler myHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case TestHandler.GUIUPDATEIDENTIFIER: myBounceView.invalidate(); break; } super.handleMessage(msg); } }; Message msg=new Message() msg.what=0x123 myHandler.sendmessage(msg)
- 要使用Handler线程中还要有一个Looper对象,负责管理MessageQueue,不间断的从MessageQueue中取出消息分发给Handler来处理,注意UI线程中已经初始了一个Looper对象,程序直接创建Handler即可,自己启动的线程,必须自己去创建Looper对象并启动它,自定义线程使用Handler和Looper的过程如下:
- 调用Looper.prepare() 创建一个Looper对象
- 创建Handler对象并重写handleMessage方法
- 调用Looper的loop方法来启动Looper
- 一个线程只能有一个Looper,但可以有多个Handler对象,每个Handler发送的消息由这个Handler本身处理。ActivityThread中定义了一个Handler,用于与ApplicationThread通信
- 异步任务AsyncTask,通常要实现AsyncTask的如下方法:
- onPreExecute:执行异步任务之前的时候执行,并且在UI线程中执行,通常在这个方法里做一些UI控件的初始化的操作
- doInBackground:在onPreExecute后执行,android会在后台的线程池中开启一个work thread来执行我们的方法,之后会把执行结果发送给onPostExecute方法
- onProgressUpdate:在doInBackground方法中调用publishProgress方法更新任务进度时会触发该方法
- execute:执行task
实现AsyncTask public class MyAsyncTask extends AsyncTask<String, Integer, byte[]> { @Override protected void onPreExecute() { super.onPreExecute(); // 在onPreExecute()中我们让ProgressDialog显示出来 progressDialog.show(); } //返回的结果会传给onPostExecute @Override protected byte[] doInBackground(String... params) { // 通过Apache的HttpClient来访问请求网络中的一张图片 HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(params[0]); byte[] image = new byte[]{}; try { HttpResponse httpResponse = httpClient.execute(httpGet); HttpEntity httpEntity = httpResponse.getEntity(); InputStream inputStream = null; ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); if(httpEntity != null && httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { // 得到文件的总长度 long file_length = httpEntity.getContentLength(); // 每次读取后累加的长度 long total_length = 0; int length = 0; // 每次读取1024个字节 byte[] data = new byte[1024]; inputStream = httpEntity.getContent(); while(-1 != (length = inputStream.read(data))) { // 每读一次,就将total_length累加起来 total_length += length; // 边读边写到ByteArrayOutputStream当中 byteArrayOutputStream.write(data, 0, length); // 得到当前图片下载的进度 int progress = (int)((total_length/(float)file_length * 100)); // 时刻将当前进度更新给onProgressUpdate方法 publishProgress(progress); //为了看出进度条效果,让程序慢点执行 Thread.sleep(1000); } } //转换为byte数组 返回给onPostExecute image = byteArrayOutputStream.toByteArray(); inputStream.close(); byteArrayOutputStream.close(); } catch (Exception e) { e.printStackTrace(); } finally { httpClient.getConnectionManager().shutdown(); } return image; } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); // 更新ProgressDialog的进度条 progressDialog.setProgress(values[0]); } @Override protected void onPostExecute(byte[] result) { super.onPostExecute(result); // 将doInBackground方法返回的byte[]解码成要给Bitmap Bitmap bitmap = BitmapFactory.decodeByteArray(result, 0, result.length); // 更新我们的ImageView控件 imageView.setImageBitmap(bitmap); // 使ProgressDialog框消失 progressDialog.dismiss(); } }
- 使用AsyncTask时必须遵守如下规则:
- 必须在UI线程中初始化AsyncTask的实例
- 必须在UI线程中调用AsyncTask的execute方法
- AsyncTask的onPreExecute,onPostExecute,doInBackground,onProgressUpdate方法不能由程序员自己调用,而是由Android系统负责调用
- 每个AsyncTask只能执行一次,多次调用将引发异常
转载于:https://www.cnblogs.com/phenixyu/p/3969094.html