最近在学习Android,有些还是需要记录下来,方便以后查询
首先
当一个应用程序启动之后,android系统会为这个应用程序创建一个主线程。这个线程非常重要,它负责渲染视图,分发事件到响 应监听器并执行, 对界面进行轮询的监听。因此,一般也叫做“UI”线程。android系统不会给应用程序的多个元素组件,建立多个线程来执行。一个视图(activity)中的多个view组件运行在同一个UI线程当中。因此,多个view组件的监听器的执行可能会相互影响。
例如:当在UI线程当中执行耗时操作,比如访问网络,访问数据库等。则会导致UI线程阻塞。当UI线程阻塞,则屏幕会出现卡死情况。这样用户体验非常差。当线程阻塞超过5秒以后,android系统有可能进行干预,弹出对话框询问是否关闭应用程序。
新建一个android project Application,
打开activity_main.xml,添加button1与button2
在MainActivity.java的onCreate中添加如下代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建动画按钮
Button btn1 = (Button)findViewById(R.id.button1);
TranslateAnimation translateAnimation = new TranslateAnimation(0, 150, 0, 0);
translateAnimation.setRepeatCount(30);//运行次数
translateAnimation.setDuration(2000);//设置越少运动速度越快
btn1.setAnimation(translateAnimation);
Button btn2 = (Button)findViewById(R.id.button2);
btn2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
启动运行,当我们点击Button2后,等待片刻后尝试再点击会出现以下
点击OK将退出程序
Android提供了两个解决方案给我们
android的UI规则
there are simply two rules to Android's single thread model;
Do not block the UI thread
不要阻塞UI线程
Do not access the Android UI toolkit from outside the UI thread
不要在UI线程之外的其他线程中,对视图当中的组件进行设置
//经典异常:
Only the original thread that created a view hierarchy can touch its views.
只有创建view的那个线程才能对其进行修改
解决方案1:post
调整onCreate代码如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建动画按钮
Button btn1 = (Button)findViewById(R.id.button1);
TranslateAnimation translateAnimation = new TranslateAnimation(0, 150, 0, 0);
translateAnimation.setRepeatCount(30);//运行次数
translateAnimation.setDuration(2000);//设置越少运动速度越快
btn1.setAnimation(translateAnimation);
Button btn2 = (Button)findViewById(R.id.button2);
btn2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
// TODO Auto-generated method stub
new Thread(new Runnable(){
@Override
public void run() {
System.out.println("线程开始");
// TODO Auto-generated method stub
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int i = 20;
v.post(new Runnable(){
@Override
public void run() {
System.out.println("post线程开始");
// TODO Auto-generated method stub
TextView tView = (TextView)v;
tView.setText("" + 100);
}
});
System.out.println("线程结束");
}
}).start();
}
});
}
而且Sleep(5000)变成了只针对Button2执行。之前是对全局进行操作。
如图:其实View.Post方式,类似于生产者与消费者的模式。每次UI线程都会在任务队列中查找一次操作,同时View.Post在里面放入自己的操作。
以上代码相当复杂,可读性差,所以官方提供了另一个方法来处理这种问题。
解决方案2:AsyncTask
官方提供了以下片段:
private class DownloadImageTask extends AsyncTask{
/*the system calls this to perform work in a workerdelivers it the parameters given to AsyncTask.execute()*/
protected Bitmap doInBackground(String... urls){
return loadImageFromNetwork(urls[0]);
}
/*The system calls this to perform work in the UI thread and delivers* the result from doInBackground()*/
protected void onFostExecute(Bitmap result){
mImageView.setImageBitmap(result);
}
}
private Button btn2 = null;
修改代码如下
private Button btn2 = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建动画按钮
Button btn1 = (Button)findViewById(R.id.button1);
TranslateAnimation translateAnimation = new TranslateAnimation(0, 150, 0, 0);
translateAnimation.setRepeatCount(30);//运行次数
translateAnimation.setDuration(2000);//设置越少运动速度越快
btn1.setAnimation(translateAnimation);
btn2 = (Button)findViewById(R.id.button2);
btn2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
// TODO Auto-generated method stub
new ChangeButtonText().execute();
}
});
}
private class ChangeButtonText extends AsyncTask{
protected Integer doInBackground(String... urls){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int i = 100;
return i;
}
protected void onFostExecute(Integer result){
btn2.setText("" + result);
}
}
最终结果: