在这种情况下,我对AppExecutors的实现是否正确?

时间:2019-04-28 17:34:26

标签: android multithreading

我曾经在github示例项目中遇到过这个AppExecutors类,但是我忘了在哪里。我发现它非常方便,因为它为我提供了多线程功能。但是我不确定在以下情况下是否可以正确执行Fragment中的代码:

  1. 使用空的ArrayList初始化一个recyclerView。
  2. 在DiskIO线程中对数据库运行查询。
  3. 然后更新适配器的数据和主线程中的视图。

我是否需要像下面所做的那样,将adapter.refreshData(list);部分显式地包入主线程Runnable?

AppExecutors.java

import android.os.Handler;
import android.os.Looper;

import androidx.annotation.NonNull;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class AppExecutors {

    private final Executor mDiskIO;

    private final Executor mNetworkIO;

    private final Executor mMainThread;

    private static volatile AppExecutors mInstance;

    private AppExecutors(Executor diskIO, Executor networkIO, Executor mainThread) {
        this.mDiskIO = diskIO;
        this.mNetworkIO = networkIO;
        this.mMainThread = mainThread;
    }

    public static AppExecutors getInstance() {
        if (mInstance == null) {
            synchronized (AppExecutors.class) {
                mInstance = new AppExecutors();
            }
        }
        return mInstance;
    }

    private AppExecutors() {
        this(Executors.newSingleThreadExecutor(), Executors.newFixedThreadPool(3),
                new MainThreadExecutor());
    }

    public Executor diskIO() {
        return mDiskIO;
    }

    public Executor networkIO() {
        return mNetworkIO;
    }

    public Executor mainThread() {
        return mMainThread;
    }

    public static void xDisk(@NonNull Runnable command) {
        getInstance().diskIO().execute(command);
    }
    public static void xNet(@NonNull Runnable command) {
        getInstance().networkIO().execute(command);
    }
    public static void xMain(@NonNull Runnable command) {
        getInstance().mainThread().execute(command);
    }

    private static class MainThreadExecutor implements Executor {
        private Handler mainThreadHandler = new Handler(Looper.getMainLooper());

        @Override
        public void execute(@NonNull Runnable command) {
            mainThreadHandler.post(command);
        }
    }
}

SomeFragment.java

...
void setUpRecyclerView() {
        TimeAllowedAdapter adapter = new TimeAllowedAdapter(getContext(), new ArrayList<>());
        rcView.setAdapter(adapter);
        rcView.setLayoutManager(new LinearLayoutManager(getContext()));
        // then fetch data and refresh list
        AppExecutors.xDisk(() -> {
            List<TimeAllowed> list = AppDatabase.getDatabase(getContext()).timeAllowedDao().getAllTimeAllowed();
            AppExecutors.xMain(() -> {
                adapter.refreshData(list);
            });
        });
    }
...

1 个答案:

答案 0 :(得分:0)

总之,是的。您需要通知适配器您的数据已更改,在这种情况下,查询数据库后该数据正在更改。

此外,作为建议,请尝试研究适配器类的invalidatenotifyDataSetChanged

此外,您可以签出this Answer来了解有关通知适配器数据集更改的更多信息。但是同样,即使我们使用的是Threads(),用于通知的代码也是在UIThread中执行的,它不过是Main线程。

希望这可以解决您的问题。