xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.MainActivity">
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?android:progressBarStyleHorizontal"/>
<TextView
android:id="@+id/tv_show_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0/100"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"/>
</LinearLayout>
MainActivity
public class MainActivityextends AppCompatActivity implements View.OnClickListener {
private ProgressBar progressBar;
private Button button;
private TextView textView;
private int progress;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
button = (Button) findViewById(R.id.button);
textView = (TextView) findViewById(R.id.tv_show_progress);
button.setOnClickListener(this);
handler = new InnerHandler();
}
@Override
public void onClick(View view) {
InnerThread thread = new InnerThread();
thread.start();
}
private class InnerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
progressBar.setProgress(msg.arg1);
textView.setText(msg.arg1+"/100");
}
}
private class InnerThread extends Thread{
@Override
public void run() {
for(int i=0;i<=100;i++){
//发消息,通知主线程更新UI
Message msg = new Message();
msg.arg1 = i;
handler.sendMessage(msg);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
之前我们说过循环中尽量不要创建新对象,但是这里,如果我们写成
Message msg = new Message();
for(int i=0;i<=100;i++){
//发消息,通知主线程更新UI
msg.arg1 = i;
......
}
这样是不行的
子线程有100次循环,所以它会发100次消息
主线程根据子线程的msg进行消息处理时,需要一定的时间,可能第一条消息还没处理完,第二条消息已经到达,而第一个消息对象还在被使用着,所以用同一个消息对象是有问题的,所以消息对象一定是不同的
假设子线程发送到了第50个消息,主线程才处理完第1个消息,这时候我们拿第一个消息对象来用是没有问题的
解决办法
private class InnerThread extends Thread{
@Override
public void run() {
for(int i=0;i<=100;i++){
//发消息,通知主线程更新UI
Message msg = Message.obtain();
msg.arg1 = i;
handler.sendMessage(msg);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
它内部就实现了对消息对象的获取过程
优化刚才代码
public class SecondActivity extends AppCompatActivity implements View.OnClickListener {
private ProgressBar progressBar;
private Button button;
private TextView textView;
private int progress;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
button = (Button) findViewById(R.id.button);
textView = (TextView) findViewById(R.id.tv_show_progress);
button.setOnClickListener(this);
handler = new InnerHandler();
}
@Override
public void onClick(View view) {
InnerThread thread = new InnerThread();
thread.start();
}
private class InnerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
if(msg.what == MESSAGE_UPDATE_PROGRESS) {
progressBar.setProgress(msg.arg1);
textView.setText(msg.arg1 + "/100");
}else if(msg.what == MESSAGE_UPDATE_COMPLETE){
Toast.makeText(MainActivity.this,"更新进度完成",Toast.LENGTH_SHORT).show();
}
}
}
public static final int MESSAGE_UPDATE_PROGRESS = 999;
public static final int MESSAGE_UPDATE_COMPLETE = 998;
private class InnerThread extends Thread{
@Override
public void run() {
for(int i=0;i<=100;i++){
//发消息,通知主线程更新UI
Message msg = Message.obtain();
msg.what = MESSAGE_UPDATE_PROGRESS;
msg.arg1 = i;
handler.sendMessage(msg);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//发出消息,标识更新进度完成
Message msg = Message.obtain();
msg.what = MESSAGE_UPDATE_COMPLETE;
handler.sendMessage(msg);
}
}
}
执行效果