非UI线程可不可以更新UI(二)
来源:互联网 发布:淘宝资产拍卖 编辑:程序博客网 时间:2024/04/30 13:32
上篇文章提到因为ViewRootImpl会在线程更新UI时检查当前线程是不是创建它的线程,子线程可以在ViewRootImpl未创建的时候尽行更新UI。下面我们来看另外一种可以在子线程更新UI的办法。
既然ViewRootImpl的checkThread方法只会检查当前更新UI的线程是不是创建它的线程。那么可不可以在子线程中构建自己的ViewRootImpl,这样在子线程中更新UI就应该不会报下面的错误:
Only the original thread that created a view hierarchy can touch its views.
由于ViewRootImpl对象的创建在WindowManager调用addView方法时创建的。所以下面我们用windowManager在子线程中创建自己的视图。
UnUIThread.java
public class UnUIThread extends Thread { private String TAG = "looper"; private Looper mLooper = null; TextView tv_thread;//要添加的textView WindowManager wManager; private Context mContext; private Handler threadHandler; public UnUIThread(Context context){ mContext = context; } public void run() { Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } createUI(); if(threadHandler==null){ threadHandler = new Handler(Looper.myLooper()){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); tv_thread.setText(msg.obj.toString()); if(msg.arg1==2){ getmLooper().quit(); } if(msg.arg1==3){ wManager.removeView(tv_thread); } } }; } Looper.loop(); } public void createUI() { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } tv_thread = new TextView(mContext); tv_thread.setTextColor(0xFF000000); tv_thread.setText("UNUIThread"); wManager = (WindowManager) mContext.getApplicationContext().getSystemService(Context.WINDOW_SERVICE); WindowManager.LayoutParams mParams = new WindowManager.LayoutParams(); mParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; mParams.format = PixelFormat.TRANSLUCENT; mParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; mParams.width = 400; mParams.height = 100; mParams.alpha = 1.0f; mParams.gravity=Gravity.BOTTOM; wManager.addView(tv_thread, mParams); } public void updateUI(){ Message msg = new Message(); msg.arg1 =1; msg.obj = String.valueOf(System.currentTimeMillis()); threadHandler.sendMessage(msg); } public void stopLoop(){ if(mLooper==null){ Toast.makeText(mContext, "mLooper", Toast.LENGTH_LONG).show(); } Message msg = new Message(); msg.arg1 =2; msg.obj = String.valueOf(System.currentTimeMillis()); threadHandler.sendMessage(msg); } public void removeUI(){ if(mLooper==null){ Toast.makeText(mContext, "mLooper", Toast.LENGTH_LONG).show(); } Message msg = new Message(); msg.arg1 =3; msg.obj = String.valueOf(System.currentTimeMillis()); threadHandler.sendMessage(msg); } public Looper getmLooper() { if(mLooper!=null){ return mLooper; }else { synchronized (this){ try { while (isAlive()&& mLooper==null){ wait(); } } catch (InterruptedException e) { e.printStackTrace(); } } return mLooper; } }}
Activity.java
public class SecondActivity extends ActionBarActivity { private Button btn_create;//创建UI private Button btn_change;//改变UI显示 private Button btn_remove;//移除UI private Button btn_stop;//停止子线程消息循环 public void autoLoad_activity_second() { btn_create = (Button) findViewById(R.id.btn_create); btn_change = (Button) findViewById(R.id.btn_change); btn_remove = (Button) findViewById(R.id.btn_remove); btn_stop = (Button) findViewById(R.id.btn_stop); } private UnUIThread unUIThread = new UnUIThread(this); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); autoLoad_activity_second(); btn_create.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(unUIThread.getState()==Thread.State.NEW){ unUIThread.start(); }else{ unUIThread = new UnUIThread(SecondActivity.this); unUIThread.start(); } if(unUIThread!=null&&!unUIThread.isAlive()){ } } }); btn_remove.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(unUIThread==null){ return; } unUIThread.removeUI(); } }); btn_stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(unUIThread==null){ return; } unUIThread.stopLoop(); } }); btn_change.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(unUIThread==null){ return; } unUIThread.updateUI(); } }); }}
效果:
Android UI相关的操作不管是在主线程还是子线程都必须依赖Looper,Handler,Message。所以必须在子线程中构建自己的消息循环机制。通过Handler机制对UI进行更新。相关原理请看http://blog.csdn.net/innost/article/details/6055793
另外由于小米系列手机对Android权限进行了限制,所以使用小米手机测试时,必须开启浮窗权限。
0 0
- 非UI线程可不可以更新UI(二)
- 非UI线程可不可以更新UI(一)
- 子线程可不可以更新UI?
- 非UI线程更新UI!?
- android UI线程与非UI线程交互(二)
- 非UI线程更新UI问题
- Android 非UI线程中更新UI
- Android 非UI线程中更新UI
- 如何实现非ui线程更新ui线程?
- 使用Thread+Handler实现非UI线程更新UI界面
- Android 在非UI线程直接更新UI信息
- 非UI线程更新UI界面的各种方法小结
- cordova 非UI线程更新UI闪退的解决办法
- Android在非UI线程中更新UI的方法
- 正确理解 非UI线程不能直接更新UI
- Android开之在非UI线程中更新UI
- 为什么我们可以在非UI线程中更新UI
- 为什么我们可以在非UI线程中更新UI
- JavaScript实现模糊匹配
- 学习OpenCV2——抠图及setmousecallback说明
- 写项目
- gitlab 7.4.5 nginx apache 配置
- LeetCode 19. Remove Nth Node From End of List
- 非UI线程可不可以更新UI(二)
- 网页中添加打印导出保存
- nagios插件之登陆router监控vrrp状态
- Centos6.7 Protocol buffer(Python)安装注意事项
- 排序算法大全
- ios 生命周期初步介绍
- 手动更新nessus的plugins
- cocos2dx LabelTTF 标签
- GCD下dispatch_once_t单例最容易理解