handler和looper在子线程的调用

来源:互联网 发布:淘宝网购支付宝限额 编辑:程序博客网 时间:2024/06/11 06:00
import android.app.Activity;import android.content.Context;import android.graphics.Color;import android.graphics.PixelFormat;import android.os.Bundle;import android.os.Handler;import android.os.Looper;import android.os.SystemClock;import android.util.Log;import android.view.Gravity;import android.view.View;import android.view.View.OnClickListener;import android.view.WindowManager;import android.widget.TextView;import android.widget.Toast;// Handler 线程间交互的一个工具public class TestHandlerActivity extends Activity {    private TextView mSubTv;        private TextView mTv;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_test_handler);        mTv = (TextView) findViewById(R.id.tv);        new SubThread().start();        mTv.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                // 结论: 只有创建这个线程的View才可以修改这个View.                mHandler.post(new Runnable() {                    @Override                    public void run() {                        mSubTv.setText("click tv");                    }                });            }        });    }    MyHandler mHandler;    class SubThread extends Thread {        int loop = 0;        @Override        public void run() {            // 下面的代码会报这个错, 因为没有调用 Looper.prepare();            // 07-06 03:11:56.875: E/AndroidRuntime(1537): java.lang.RuntimeException:            // Can't create handler inside thread that has not called Looper.prepare()            Looper.prepare();//            Toast.makeText(TestHandlerActivity.this, "subthread", 0).show();            // 如果在 onCreate 里开启子线程, 是可以"修改"UI的, 其实不是修改, onCreate 里, 界面还没有绘制出来//             mTv.setText 等方法其实只是修改了一个对象的属性值, 不是修改UI. 所以睡眠一会就不行了//            SystemClock.sleep(200);//            mTv.setText("subthread");////             这里就不会报错//            Toast.makeText(TestHandlerActivity.this, "subthread", 0).show();            mSubTv = new TextView(TestHandlerActivity.this);            // 给view对象中的控件设置相应的属性            mSubTv.setTextColor(Color.BLACK);            mSubTv.setText("subthread handler");             // 创建一个LayoutParams, 指定布局参数            WindowManager manager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);            WindowManager.LayoutParams lp = new WindowManager.LayoutParams();            lp.height = WindowManager.LayoutParams.WRAP_CONTENT;            lp.width = WindowManager.LayoutParams.WRAP_CONTENT;            // 干嘛的不知道, 只有设置了gravity为Gravity.LEFT+Gravity.TOP, 才能设置x,y            lp.gravity = Gravity.LEFT + Gravity.TOP;            lp.x = 100;            lp.y = 200;            lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;            lp.format = PixelFormat.TRANSLUCENT;            //mParams.type = WindowManager.LayoutParams.TYPE_TOAST;            // 必须设置下面这种type, 控件才能拖动. 注意权限            lp.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;            // 使用WindowManager吧view对象按照layoutParams显示            manager.addView(mSubTv, lp);            mHandler = new MyHandler();//            while (loop <= 1) {//                mHandler.sendEmptyMessageDelayed(0, 1000);//                loop++;//            }//                        Looper.loop();        }    }    class MyHandler extends Handler {        public void handleMessage(android.os.Message msg) {            // 子线程的Handler可以弹吐司            Toast.makeText(TestHandlerActivity.this, "subthread handler", 0).show();            // 但是不能修改主线程创建的UI, 否则会报错            // 07-06 02:58:35.343: E/AndroidRuntime(1426): android.view.ViewRoot$CalledFromWrongThreadException:            // Only the original thread that created a view hierarchy can touch its views.            //mTv.setText("Subthread handler");            // 但是可以使用 WindowManager 修改UI//             创建view对象            TextView tv = new TextView(TestHandlerActivity.this);            // 给view对象中的控件设置相应的属性            tv.setTextColor(Color.BLACK);            tv.setText("subthread handler");             // 创建一个LayoutParams, 指定布局参数            WindowManager manager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);            WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();            mParams.height = WindowManager.LayoutParams.WRAP_CONTENT;            mParams.width = WindowManager.LayoutParams.WRAP_CONTENT;            // 干嘛的不知道, 只有设置了gravity为Gravity.LEFT+Gravity.TOP, 才能设置x,y            mParams.gravity = Gravity.LEFT + Gravity.TOP;            mParams.x = 100;            mParams.y = 200;            mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;            mParams.format = PixelFormat.TRANSLUCENT;            //mParams.type = WindowManager.LayoutParams.TYPE_TOAST;            // 必须设置下面这种type, 控件才能拖动. 注意权限            mParams.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;            // 使用WindowManager吧view对象按照layoutParams显示            manager.addView(tv, mParams);            Log.i("SubThread", "subthread handler");        };    };}

0 0
原创粉丝点击