Monitor项目开发走过的路~子线程Toast全解析
来源:互联网 发布:重庆专业u盘数据恢复 编辑:程序博客网 时间:2024/06/07 07:33
Toast在Android开发中是很常用的,可以很便捷清楚的反映给用户一些重要的实时信息。在Monitor项目开发中在Toast的使用上也是遇到了一些问题。平时最经常用的方法就是在Activity中调用Toast.makeText().show()方法,我们需要传入当前的上下文环境,通常传入当前的Activity.this即可。可是项目中与服务器端交互的代码是我们后端开发人员写的,他让我将里面的日志都用Toast显示出来。因为是在一个非Activity的类里面,也就没有办法传入Context变量。最后想到了看书的时候获取全局context的方法。新建一个MyApplication类
public class MyApplication extends Application{ private static Context context; @Override public void onCreate() { super.onCreate(); context=getApplicationContext(); } public static Context getContext(){ return context; }}
这样你就可以轻易地在项目中的任何一个地方调用MyApplication.getContext()静态方法获取全局Context
Toast.makeText(MyApplication.getContext(),"这是Toast",Toast.LENGTH_SHORT).show();
运行程序之后抛出了下面这样的异常
网上一番搜寻之后找到了问题所在,因为我的Toast是在一个自己创建的子线程中运行的,子线程在默认情况下并没有一个消息循环loop与它们相关联。looper是用来给线程处理消息用的,线程默认情况下没有looper对象,也就是线程中的消息不会被处理,自然将消息直接丢在线程中的时候是不会被处理的。必须在线程中创建一个Looper实例。主线程在创建的时候就直接绑定初始化了一个looper对象,所以我们平时在主线程使用Toast是没有问题的。所以子线程中使用Toast要加入下面两行代码创建Looper并使它运行起来处理子线程的消息循环。
Looper.prepare();Toast.makeText(MyApplication.getContext(),"下载成功",Toast.LENGTH_SHORT).show();Looper.loop();
这样一来就可以在子线程中正常使用Toast了,但是千万别以为这样就万事东风了,我在Monitor项目中有非常多的地方要使用Toast,于是乎就把所有使用的地方都创建一个Looper。果不其然Bug就出现了,这个问题很难发现,在多次运行应用后偶尔会出现闪退的情况。思前想后也是没有找的问题的根源。于是手机USB调试一直放在那里等待Bug的出现。真的是等到花儿也谢了,终于看到了打印出两句日志
11-24 15:13:26.188 23853-2029/com.qinlong275.android.monitor A/ Looper: Could not create epoll instance: Too many open files11-24 15:13:26.188 23853-23853/com.qinlong275.android.monitor E/ art: ashmem_create_region failed for 'indirect ref table': Too many open files
网上查了一下说这个应该是创建了太多Looper的原因,果然是由于我每个Toast都新创建了一个Toast造成的。于是想到可以将每个子线程的Toast操作交给主线程来运行,主线程有默认的Looper 循环消息,以及对应的Handler来处理消息任务。
public class ConnectActivity extends SingleFragmentActivity { //在一些类中的子线程中使用Toast,可以发到这个主线程的Handler解决,防止子线程Loop太多带来的各种问题 public static Handler mHandler=new Handler(){ @Override public void handleMessage(Message msg) { String str=(String)msg.obj; Toast.makeText(MyApplication.getContext(),str,Toast.LENGTH_SHORT).show(); } }; @Override protected Fragment createFragment() { return ConnectFragment.newInstance(); }}
我在项目的第一个Activity中创建了一个Handler来处理主线程的消息,在public void handleMessage(Message msg){}方法中来处理子线程Toast.并将这个Handler设置为静态成员,这样便可以在任何一个地方来使用。好了处理消息机制搭建好了,就可以在应用端向主线程发消息了。
Message msg=new Message();msg.obj="升级出现错误";ConnectActivity.mHandler.sendMessage(msg);msg=null;
这样就可以将子线程Toast任务交给主线程来处理,就解决了之前的所有问题。
- Monitor项目开发走过的路~子线程Toast全解析
- Monitor项目开发走过的路~自定义AlertDialog,设置子view
- Monitor项目开发走过的路~透明效果的实现
- Monitor项目开发走过的路~定义启动展览页
- Monitor项目开发走过的路~RecyclerView添加子项分割线
- Monitor项目开发走过的路~透明Dialog型Activity
- Monitor项目开发走过的路~实现一个类似命令行形式的TextView
- Monitor项目开发走过的路~android:windowFullscreen与软键盘冲突问题
- Monitor项目开发走过的路~一键关闭APP(所有Activity)
- Android 子线程中Toast的问题
- 子线程中添加Toast的方法
- Toast不显示的原因和在子线程中使用方法以及Looper类详细解析
- 子线程中Toast
- android 子线程 Toast
- 子线程中Toast
- Android开发之在子线程中使用Toast
- 子线程中使用Toast
- 子线程中发Toast
- 学习计划
- 使用RxJava的retryWhen操作符实现token过期自动刷新
- python入门第一天——控制流
- 复制状态机(State Machine Replication)
- 在Ubuntu 16.04配置VNC Server (灰屏问题解决)
- Monitor项目开发走过的路~子线程Toast全解析
- JavaScript--函数声明、函数表达式、匿名函数、立即执行函数
- 到底怎么做需求分析,技术调研,技术设计?
- C++ 数据结构-树状数组
- 互联网技术体验
- Add to List 657. Judge Route Circle
- 虚幻4游戏菜单功能的实现
- ViewPager实现循环广告
- 关于热点的一些思考