Handelr的异步回掉机制
来源:互联网 发布:淘宝人肉一个人多钱 编辑:程序博客网 时间:2024/06/08 04:25
1.通过Handelr实现UI线程与子线程的异步加载,首先要在AndroidMainfest.xml中声明访问权限
<uses-permission android:name="android.permission.INTERNET"/>
2.回掉方法,我们通过创建接口来实现:
public interface MyImageCallback { void onSuccess(Bitmap bitmap);//访问成功,并从网络上获取一张图片 void onFail(Exception e,String msg);//访问失败,抛出异常以及消息 void onProgress(Float percent);//进度条}3.由于访问网络是耗时操作,所以我们要开辟子线程来执行耗时操作:
public class ImageRunnable implements Runnable, Handler.Callback { private String url; private MyImageCallback callback; /* * Message 产品 * MessageQueue 仓库(正常编程的话永远用不到) * Looper 循环 * Handler 物流 * Handler.Callback 回调接口 * 任何与网络连接都不能在主线程中运行 * * */ private Handler handler; public ImageRunnable(String url, MyImageCallback callback) { this.url = url; this.callback = callback; /*查找到的资料: *Handler一定要在主线程实例化吗? * new Handler()和new Handler(Looper.getMainLooper())的区别 * 如果你不带参数的实例化:Handler handler = new Handler(); * 那么这个会默认用当前线程的looper * 一般而言,如果你的Handler是要来刷新操作UI的, * 那么就需要在主线程下跑。 *情况: *1.要刷新UI,handler要用到主线程的looper。 * 那么在主线程 Handler handler = new Handler(); * 如果在其他线程,也要满足这个功能的话, * 要Handler handler = new Handler(Looper.getMainLooper()); * *2.不用刷新ui,只是处理消息。 * 当前线程如果是主线程的话,Handler handler = new Handler(); * 不是主线程的话,Looper.prepare(); * Handler handler = new Handler();Looper.loop(); * 或者Handler handler = new Handler(Looper.getMainLooper()); *若是实例化的时候用Looper.getMainLooper()就表示放到主UI线程去处理。 * 如果不是的话,因为只有UI线程默认Loop.prepare();Loop.loop();过, * 其他线程需要手动调用这两个,否则会报错。 * * * */ handler = new Handler(Looper.getMainLooper(),this); } @Override public void run() { try { HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("GET"); connection.setDoInput(true); int code = connection.getResponseCode(); if (code == 200) { InputStream is = connection.getInputStream(); int contentLength = connection.getContentLength(); int length; ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buffer = new byte[102400]; while ((length = is.read(buffer)) != -1){ bos.write(buffer,0,length); handler.obtainMessage(2, bos.size(), contentLength).sendToTarget(); } byte[] bytes = bos.toByteArray(); Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); /*handler数据传递的三种方式 * 方式一: * Message message = new Message();message创建方式(不推荐) * Message message = Message.obtain(handler,0,String.valueOf(i + 1));//推荐使用 * message.sendToTarget(); * handler.sendMessage(message); * 方式二: * Message message = Message.obtain(); * message.obj = String.valueOf(i + i); * message.what = 0; * handler.sendMessage(message); * 方式三: *handler.obtainMessage(0,String.valueOf(1 + i)).sendToTarget() * * */ handler.obtainMessage(0,bitmap).sendToTarget(); }else{ RuntimeException exception = new RuntimeException("response" + code); String string = "服务器异常"; Bundle bundle = new Bundle(); bundle.putString("str",string); bundle.putSerializable("exception",exception); Message message = handler.obtainMessage(1); message.setData(bundle); handler.sendMessage(message); } } catch (IOException e) { String str = "网络异常"; /* * 当要传递多条数据时, * 采用bundle打包数据(bundle使用方法类似于map集合), * 毕竟message.obj只能赋值一种类型的数据, * 如果是同一个进程,最好用setData, *message.obj一般是Messenger类来用来跨进程传递可序列化的对象的, * 这个比setData,更消耗性能一些。 * */ Bundle bundle = new Bundle(); bundle.putString("str",str); bundle.putSerializable("exception",e); Message message = handler.obtainMessage(1); message.setData(bundle); handler.sendMessage(message); } } @Override public boolean handleMessage(Message msg) { switch (msg.what) { case 0: callback.onSuccess((Bitmap) msg.obj); break; case 1: Bundle data = msg.getData(); String string = data.getString("str"); Exception exception = (Exception) data.getSerializable("exception"); callback.onFail(exception,string); break; case 2: int size = msg.arg1; int length = msg.arg2; float percent = size * 100.0f / length; callback.onProgress(percent); break; } return true;//返回值true代表message数据已经传输完成 }}
3.在UI线程中通过回调接口来获取子线程中存储的数据:
public class MainActivity extends AppCompatActivity implements MyImageCallback{ private ImageView imageView; private TextView text; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = (ImageView) findViewById(R.id.main_image); text = (TextView) findViewById(R.id.main_tv); ImageRunnable runnable = new ImageRunnable("http://p4.so.qhmsg.com/t018349127914f495ce.jpg", this); new Thread(runnable).start(); } @Override public void onSuccess(Bitmap bitmap) { imageView.setImageBitmap(bitmap); } @Override public void onFail(Exception e, String msg) { e.printStackTrace(); Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show(); } @Override public void onProgress(Float precent) { text.setText(String.format(Locale.CHINA,"%.2f%%",precent));//显示加载文本图片的百分比 }}
0 0
- Handelr的异步回掉机制
- handelr post 的分析(转载)
- .Net的异步机制
- jQuery的异步机制
- 关于Ajax的异步机制
- Windows的异步选择机制
- CAsyncSocket类的异步机制
- js的setTimeout异步机制
- 异步消息机制的理解
- 异步通知机制的总结
- 异步消息的传递-回调机制
- 异步消息的传递-回调机制
- 异步消息的传递-回调机制
- 异步消息的传递-回调机制
- 异步消息的传递-回调机制
- [zz]异步消息的传递-回调机制
- 异步消息的传递-回调机制
- 异步消息的传递-回调机制
- 插入排序
- Android面经2016
- C语言的发展及其版本
- Codeforces Round #369 (Div. 2) 711D Directed Roads (dfs)
- CSS中padding的特殊性
- Handelr的异步回掉机制
- Activity切换时的效果
- ccc 2016 s3
- 系统启动过程
- 离线Ubuntu系统安装codeblocks,fftw
- LIS&LICS
- 用NPOI、C#操作Excel表格生成班级成绩单
- Shell 函数
- socket 简单介绍与例子