这个误区是:子线程不能更新 UI ,其应该分类讨论,而不是绝对的。
半小时前,我的 XRecyclerView 群里面,一位群友私聊我,问题是:
为什么我的子线程更新了 UI 没报错?
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- title = (TextView) findViewById(R.id.title_tips);
- doGet("http;//www.baidu.com", new Callback() {
- @Override
- public void onFailure(Request request, IOException e) {
- }
- @Override
- public void onResponse(Response response) throws IOException {
- title.setText(response.body().string()); // 这里在子线程更新了 text
- }
- });
- }
- private void doGet(String url,Callback callback) {
- OkHttpClient client = new OkHttpClient();
- Request.Builder builder = new Request.Builder();
- Request request = builder.url(url).get().build();
- client.newCall(request).enqueue(callback);
- }
简单解析下。他用了 OkHttp 的异步 enqueue 的请求,并在成功后更新了 textView 的 text。
那么这样来说,按照我们被一直灌输的原理: 子线程不能刷新UI,上面这段代码妥妥地爆错啊。
上面的代码不一定爆错,它还会稳稳的顺利执行。
你可以尝试下。嫌麻烦,你可以运行下下面这段
的子线程更新UI代码
- 通透
- public class TestActivity extends Activity {
- private TextView title;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- title = (TextView) findViewById(R.id.title_tips);
- new Thread(
- new Runnable() {
- @Override
- public void run() {
- // 子线程更新UI
- title.setText("我 tm 妥妥地执行完毕");
- }
- }
- ).start();
- }
- }
试了的都知道,真 tm 执行了没爆错。
在看到他发给我的代码,
里面的部分,一切已经明了,这也是我之前面试几年经验的人设过的坑。下面我直接讲原因,源码分析那些你们自己去看吧,
- onCreate
。
- 你应该去看
- void checkThread() {
- // 该方法是 viewRootImpl.java 内部代码
- if (mThread != Thread.currentThread()) {
- throw new CalledFromWrongThreadException(
- "Only the original thread that created a view hierarchy can touch its views.");
- }
- }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- title = (TextView) findViewById(R.id.title_tips);
- new Thread(
- new Runnable() {
- @Override
- public void run() {
- try {
- // 等待 onResume 执行完,让 viewRootImpl 初始化完成
- Thread.sleep(3000); // ---------- 这里,看这里
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- title.setText("我执行不了");
- }
- }
- ).start();
- }
来源: http://www.cnblogs.com/linguanh/p/7898996.html