Android开发中,我们经常会头疼UI更新的问题,尤其是跨线程更新UI。今天我们就来聊一聊具体有哪些能够可靠更新UI的的方式:
1、EventBus更新UI:该方式几乎没有使用环境限制,且是线程安全的。不足之处是内部通过主解实现的,有一点点影响效率;
2、RunOnUiThread更新UI:是Activity中的方法,在线程中我们需要告诉系统是哪个activity调用,所以需要在前面指明调用的activity,亦即:***Activity.this.runOnUiThread()。可以说是专门为在子线程中更新UI设计的而且高效;
3、Handller更新UI:也是一种跨线程更新UI的方式,与EventBus一样,几乎可以在所有场合使用,在使用上稍微有一点繁琐;
4、Interface接口回调更新UI:比较常用的一种更新方式,局限性在于:只能直接用在主线程中;
5、runOnUiThread + EventBus更新UI:前面方式1和2的组合;
6、runOnUiThread + Interface接口:前面方式2和4的组合;
7、子线程 + runOnUiThread + Interface接口更新UI;
8、子线程 + EventBus更新UI。
其中常用的应该是前面3中。具体用法如下:
xml中布局:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_thread"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.haoyue.demo_list.thread.ThreadActivity">
<TextView
android:id="@+id/tvTextThread"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp"
android:layout_centerInParent="true"
android:text="UI更新"
android:textSize="16sp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/btChildThreadEventBus"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_margin="5dp"
android:background="@drawable/button_background"
android:text="子线程new Thread + EventBus更新UI"
android:textAllCaps="false"/>
<Button
android:id="@+id/btChildThread_RunOnUiThread_Inter"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_margin="5dp"
android:background="@drawable/button_background"
android:text="子线程 → runOnUiThread →Interface接口更新UI"
android:textAllCaps="false"/>
<Button
android:id="@+id/btRunOnUiThread_Inter"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_margin="5dp"
android:background="@drawable/button_background"
android:text="runOnUiThread线程 → Interface接口更新UI"
android:textAllCaps="false"/>
<Button
android:id="@+id/btRunOnUiThread_EventBus"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_margin="5dp"
android:background="@drawable/button_background"
android:text="runOnUiThread + EventBus更新UI"
android:textAllCaps="false"/>
<Button
android:id="@+id/btUpdateUI_Handller"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_margin="5dp"
android:background="@drawable/button_background"
android:text="通过Handller测试接口回调更新UI"
android:textAllCaps="false"/>
<Button
android:id="@+id/btUpdateUI_EventBus"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_margin="5dp"
android:background="@drawable/button_background"
android:text="通过EventBus测试子线程回调接口更新UI"
android:textAllCaps="false"/>
<Button
android:id="@+id/btRunOnUiThread"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_margin="5dp"
android:background="@drawable/button_background"
android:text="通过RunOnUiThread测试更新UI"
android:textAllCaps="false"/>
<Button
android:id="@+id/btInterface"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_margin="5dp"
android:background="@drawable/button_background"
android:text="通过Interface接口测试更新UI"
android:textAllCaps="false"/>
</LinearLayout>
</RelativeLayout>
interface接口:
public interface InterfaceThread {
void update(String string);
}
Activity代码:
public class ThreadActivity extends AppCompatActivity {
@BindView(tvTextThread)
TextView mTvTextThread;
@BindView(R.id.btChildThreadEventBus)
Button mBtChildThreadEventBus;
@BindView(R.id.btChildThread_RunOnUiThread_Inter)
Button mBtChildThreadRunOnUiThreadInter;
@BindView(R.id.btRunOnUiThread_Inter)
Button mBtRunOnUiThreadInter;
@BindView(R.id.btRunOnUiThread_EventBus)
Button mBtRunOnUiThreadEventBus;
@BindView(R.id.btUpdateUI_Handller)
Button mBtUpdateUIHandller;
@BindView(R.id.btUpdateUI_EventBus)
Button mBtUpdateUIEventBus;
@BindView(R.id.btRunOnUiThread)
Button mBtRunOnUiThread;
@BindView(R.id.btInterface)
Button mBtInterface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_thread);
ButterKnife.bind(this);
EventBus.getDefault().register(this);
}
InterfaceThread mThread = new InterfaceThread() {
@Override
public void update(String string) {
mTvTextThread.setText(string);
}
};
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
mTvTextThread.setText("通过Handler更新UI的测试");
break;
}
}
};
public void onEventMainThread(EventMsg event) {
mTvTextThread.setText(event.string + "\n 灰色");
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
@OnClick({R.id.btChildThread_RunOnUiThread_Inter, R.id.btInterface,
R.id.btRunOnUiThread_Inter, R.id.btRunOnUiThread_EventBus,
R.id.btUpdateUI_Handller, R.id.btUpdateUI_EventBus,
R.id.btRunOnUiThread, R.id.btChildThreadEventBus})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.btChildThreadEventBus:
new Thread(new Runnable() {
@Override
public void run() {
String msg = "子线程 + EventBus更新UI的测试成功";
EventBus.getDefault().post(new EventMsg(msg));
}
}).start();
break;
case R.id.btChildThread_RunOnUiThread_Inter:
new Thread(new Runnable() {
@Override
public void run() {
ThreadActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
String msg="子线程→runOnUiThread→接口更新";
mThread.update(msg);
}
});
}
}).start();
break;
case R.id.btRunOnUiThread_Inter:
ThreadActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
String msg ="runOnUiThread + Interface接口更新UI";
mThread.update(msg );
}
});
break;
case R.id.btRunOnUiThread_EventBus:
ThreadActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
String msg = "runOnUiThread + EventBus更新UI";
EventBus.getDefault().post(new EventMsg(msg));
}
});
break;
case R.id.btUpdateUI_Handller:
Message msg = new Message();
msg.what = 1;
mHandler.sendMessage(msg);
break;
case R.id.btUpdateUI_EventBus:
String msg = "通过EventBus更新UI的测试成功";
EventBus.getDefault().post(new EventMsg(msg));
break;
case R.id.btRunOnUiThread:
mTvTextThread.setText("通过RunOnUiThread更新UI测试成功");
break;
case R.id.btInterface:
mThread.update("通过Interface接口回调更新UI的测试成功");
break;
}
}
}
以上8中更新方式,亲测均能够成功。实际开发中,用的最多的还是前面4中方式,尤其是方式1、3、4三种方式。