handler和looper在子线程的调用

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值