java - Main UI 和 AsyncTask 是否在同一个线程上运行?

标签 java android multithreading android-asynctask

我在尝试显示加载消息时发现了这个,或者你可以在我的 Activity 上说一个进度条。

我尝试在 UI 线程和 AsyncTask 中使用 Thread.currentThread.getId() 打印线程 ID。两者都打印 1。

如果两者都在同一个线程上运行,那么我们如何在运行复杂任务(建议在doInBackground 中执行)的同时更改 UI(建议在 onPreExecute 中执行)。

请解释

最佳答案

doInBackground() 在后台线程上运行,然后仅当您正确使用 AsyncTask 时。

doInBackground() 无法直接更改 UI,因为它在后台线程上运行。如果您需要在 doInBackground() 运行时进行更改,请调用 publishProgress()。这会触发对 onProgressUpdate() 的调用,并将在主应用程序线程上调用。

例如,这个保留的 fragment 有一个 AsyncTask,它会在单词可用时通过它的 ArrayAdapter 将单词添加到 ListView (使用 Thread.sleep() 模拟网络 I/O 的延迟):

/***
  Copyright (c) 2008-2014 CommonsWare, LLC
  Licensed under the Apache License, Version 2.0 (the "License"); you may not
  use this file except in compliance with the License. You may obtain   a copy
  of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
  by applicable law or agreed to in writing, software distributed under the
  License is distributed on an "AS IS" BASIS,   WITHOUT WARRANTIES OR CONDITIONS
  OF ANY KIND, either express or implied. See the License for the specific
  language governing permissions and limitations under the License.

  From _The Busy Coder's Guide to Android Development_
    https://commonsware.com/Android
 */

package com.commonsware.android.async;

import android.app.ListFragment;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Toast;
import java.util.ArrayList;

public class AsyncDemoFragment extends ListFragment {
  private static final String[] items= { "lorem", "ipsum", "dolor",
      "sit", "amet", "consectetuer", "adipiscing", "elit", "morbi",
      "vel", "ligula", "vitae", "arcu", "aliquet", "mollis", "etiam",
      "vel", "erat", "placerat", "ante", "porttitor", "sodales",
      "pellentesque", "augue", "purus" };
  private ArrayList<String> model=new ArrayList<String>();
  private ArrayAdapter<String> adapter=null;
  private AddStringTask task=null;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setRetainInstance(true);

    task=new AddStringTask();
    task.execute();

    adapter=
        new ArrayAdapter<String>(getActivity(),
                                 android.R.layout.simple_list_item_1,
                                 model);
  }

  @Override
  public void onViewCreated(View v, Bundle savedInstanceState) {
    super.onViewCreated(v, savedInstanceState);

    getListView().setScrollbarFadingEnabled(false);
    setListAdapter(adapter);
  }

  @Override
  public void onDestroy() {
    if (task != null) {
      task.cancel(false);
    }

    super.onDestroy();
  }

  class AddStringTask extends AsyncTask<Void, String, Void> {
    @Override
    protected Void doInBackground(Void... unused) {
      for (String item : items) {
        if (isCancelled())
          break;

        publishProgress(item);
        SystemClock.sleep(400);
      }

      return(null);
    }

    @Override
    protected void onProgressUpdate(String... item) {
      if (!isCancelled()) {
        adapter.add(item[0]);
      }
    }

    @Override
    protected void onPostExecute(Void unused) {
      Toast.makeText(getActivity(), R.string.done, Toast.LENGTH_SHORT)
           .show();

      task=null;
    }
  }
}

(来自 this sample projectthis book 中描述)

关于java - Main UI 和 AsyncTask 是否在同一个线程上运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34990553/

相关文章:

java - TimeHandler 中抛出 IndexOutOf range 异常

c# - 多处理器和性能

multithreading - Dart 是单线程的,但为什么它使用 Future Objects 并执行异步操作

c# - 为什么值变量不改变?

java - libgdx 中多个摄像机和视口(viewport)的问题

java - jScrollPane 无法添加组件

Java:JTable 中的控制台输出

java - Java switch 语句和枚举的有趣结果

android - 我们应该在 Strings.xml 中还是在布局 xml 文件本身中给出字符串值

android - 使用 Dagger2 (Robolectric) 模拟 jetpack ViewModel 进行单元测试