Android线程间通信二主线程发消息给子线程
来源:互联网 发布:剑灵外形数据 编辑:程序博客网 时间:2024/04/28 22:11
线程间通信是Android开发中经常使用的技术,上篇文章示范了子线程完成耗时操作把结果告诉主线程,不过上个例子有个漏洞,我们常见的应用都是需要下载大量图片的,比如淘宝、京东、QQ、微信等都是在使用过程中需要大量下载图片,如果我们每次下载一张图片都new出一个子线程,那么我们应用很有可能因为创建太多子线程而崩溃,这个问题该怎么解决呢?
问题是出在为了下载图片,创建了过多的子线程引起的,那么如果我们只创建一个子线程,让这一个子线程去下载图片,当一张图片下载完了继续下载下一张图片,这样就把问题解决了,这样就可以当主线程需要下载的时候告诉子线程,让子线程去下载,子线程下载完后把结果告诉主线程;
结果图:
代码:
import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Bundle;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;import android.widget.TextView;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;/** * Created by wyx on 2015/12/28. */public class QueueActivity extends AppCompatActivity implements View.OnClickListener { private Button mBtnAddDownload; private TextView tvDownloadCount; private int allCount; private int successCount; private int failedCount; static final int DOWNLOAD_SUCCESS = 0; static final int DOWNLOAD_FAILED = 1; static final int ADD_DOWNLOAD = 2; Handler mSubThreadHandler; Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case DOWNLOAD_SUCCESS: successCount++; break; case DOWNLOAD_FAILED: failedCount ++; break; } StringBuilder buffer = new StringBuilder(); buffer.append("下载总数:").append(allCount).append('\n') .append("成功次数:").append(successCount).append('\n') .append("失败次数:").append(failedCount); tvDownloadCount.setText(buffer.toString()); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_queue); initUI(); startQueue(); } private void initUI() { this.mBtnAddDownload = (Button)findViewById(R.id.btn_add_download); this.tvDownloadCount = (TextView) findViewById(R.id.tv_download_count); mBtnAddDownload.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.btn_add_download: // 增加一天下载数 allCount++; // 告诉子线程添加下载任务 mSubThreadHandler.sendEmptyMessage(ADD_DOWNLOAD); break; } } /** * 开启一个子线程,使用Looper+Handler完成一个轮循处理机制, */ private void startQueue() { new Thread(new Runnable() { @Override public void run() { Looper.prepare(); mSubThreadHandler = new Handler(Looper.myLooper()){ @Override public void handleMessage(Message msg) { switch (msg.what){ case ADD_DOWNLOAD: dowanload(); break; } } }; Looper.loop(); } }).start(); } private void dowanload() { InputStream is = null; try { URL url = new URL(MainActivity.IMG_PATH); // 获取网络连接对象 HttpURLConnection con = (HttpURLConnection) url.openConnection(); // 得到网络资源输入流 is = con.getInputStream(); // 利用图片工厂把输入流转换成图片 Bitmap bitmap = BitmapFactory.decodeStream(is); // 新建消息对象 Message msg = new Message(); // 设置消息动作含义 msg.what = DOWNLOAD_SUCCESS; msg.obj = bitmap; // 完成下载发送消息给主线程; mHandler.sendMessage(msg); } catch (MalformedURLException e) { // 出现URL异常发送给主线程 Message msg = new Message(); msg.what = DOWNLOAD_FAILED; // mHandler.sendEmptyMessage(IMG_DOWNLOAD_URL_ERROR); mHandler.sendMessage(msg); } catch (IOException e) { // 出现IO异常发送给主线程 Message msg = new Message(); msg.what = DOWNLOAD_FAILED; mHandler.sendMessage(msg); }finally{ // 关闭流 if(is != null){ try { is.close(); } catch (IOException e) { } } } } @Override public void finish() { super.finish(); if(mSubThreadHandler!=null){ // 队列不需要的时候要清除掉 mSubThreadHandler.getLooper().quit(); } }}布局文件代码:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="8dp"> <Button android:id="@+id/btn_add_download" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="增加一次下载" android:textSize="16sp" /> <TextView android:id="@+id/tv_download_count" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="16sp" android:layout_marginTop="8dp" /></LinearLayout>分析:
有上一篇例子的内容基础,这次改变就在于把下载操作都放在了一个线程里面,使用Looper+Handler的方式进行循环处理子线的消息;在onCreat()方法中调用了startQueue(),在startQueue()中开启了一个子线程,子线程的run()方法里调用了Looper.prepare(),mSubThreadHandler = new Handler(Looper.myLooper()),Looper.loop(),这三个步骤在子线程中不能缺少才能完成循环队列的设置,其中mSubThreadHandler = new Handler(Looper.myLooper())是表示new出一个当前线程的消息处理器,当前线程是子线程,所以是子线程的消息处理器,当主线程使用mSubThreadHandler发送消息时,是在子线程中处理消息;
0 0
- Android线程间通信二主线程发消息给子线程
- Android主线程发消息给子线程
- 【原】qt4 子线程给主线程发消息,发数据,通信,qthread gui postevent emit
- qt4 子线程给主线程发消息,发数据,通信,qthread gui postevent emit
- qt4 子线程给主线程发消息,发数据,通信,qthread gui postevent emit .
- android 主线程与子线程互发消息,以及自己给自己发消息
- Android消息通信机制(主线程发消息到子线程)
- 【Android】从主线程向子线程发消息
- Android Handler:子线程发消息到UI主线程
- Android中主线程给子线程发Message
- Android子线程给主线程发送消息
- 主线程给子线程发送消息
- Android子线程与主线程通信
- android 主线程与子线程通信
- Android 子线程与主线程间的通信
- 在 Android 中主线程如何给子线程发 Message?
- Android消息通信机制(子线程向主线程通信).txt
- Android中Handler从子线程发消息到主线程回调消息全过程
- Json在线工具使用说明
- 腾讯网迷你版如何关闭
- bzoj1023 仙人掌图 树形dp
- 2015福建省赛 Common Tangents 2213 (简单数学几何)
- 搭建Android开发环境
- Android线程间通信二主线程发消息给子线程
- 关于百度地图的基础地图和定位功能
- 字符串中统计单词个数
- DFS
- LTE信令
- uva714
- 水浒传之于公司治理
- 年终总结
- 获取Android设备的唯一识别码