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");
};
};
}
handler和looper在子线程的调用
最新推荐文章于 2023-06-13 23:13:33 发布