首页 > 解决方案 > 从 AsyncTask 内部动态更新 RecycleView

问题描述

我有以下代码:

protected void onCreate(Bundle savedInstanceState) {
    RecyclerView recyclerView;
    DeviceAdapter deviceAdapter;
    List<Device> deviceList;

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final Context context = this;

    g.IP = cf.getIP(this);
    g.subNet = g.IP.substring(0, g.IP.lastIndexOf(".") + 1);

    deviceList = new ArrayList<>();
    recyclerView = findViewById(R.id.recyclerView);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));

    new AsyncTask<Void, Void, Void>() {

        @Override
        protected Void doInBackground(Void... params) {
            for(int i = 1; i < 256; i++) {
                if(cf.isUp(g.subNet + i, 80)) {
                    deviceList.add(new Device(g.subNet + i, "PAUSED", "N/A"));
                }
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);

            deviceAdapter = new DeviceAdapter(context, deviceList);
            recyclerView.setAdapter(deviceAdapter);
        }
    }.execute();
}

它会检查主机是否在线,以及它们的端口 80 是否打开,然后在扫描结束时将它们全部添加到RecyclerView.

我想知道如何添加:

deviceAdapter = new DeviceAdapter(context, deviceList);
recyclerView.setAdapter(deviceAdapter);

doInBackground()if 语句,像这样:

@Override
protected Void doInBackground(Void... params) {
    for(int i = 1; i < 256; i++) {
        if(cf.isUp(g.subNet + i, 80)) {
            deviceList.add(new Device(g.subNet + i, "UP", "OPEN"));

            deviceAdapter = new DeviceAdapter(context, deviceList);
            recyclerView.setAdapter(deviceAdapter);
        }
    }
    return null;
}

但不会使我的应用程序崩溃,以便RecyclerView在将新项目添加到时立即更新deviceList<>,而不是在任务完成时立即更新。

标签: android

解决方案


您的应用程序正在崩溃,因为只有主线程可以处理 UI 元素,例如RecyclerView. AsyncTask因此,您需要做的是创建一个侦听器,每当您找到新设备时都会调用该侦听器。

例子:

public interface OnDeviceFoundListener {
    void onDeviceFound(Device device);
}

@Override
protected void doInBackground(Void... params) {
    for (int i = 1; i < 256; i++) {
        if (cf.isUp(g.subNet + 1, 80)) {
            listener.onDeviceFound(new Device(g.subNet + 1, "UP", "OPEN"));
        }
    }
}

然后,在RecyclerView所在的Activity或者Fragment中,你会实现这个监听接口,例如:

public class MyActivity extends AppCompatActivity implements OnDeviceFoundListener {

    private List<Device> devices;

    @Override
    public void onDeviceFound(Device device) {
        devices.add(device);
        deviceAdapter = new DeviceAdapter(context, devices);
        recyclerView.setAdapter(adapter);
        recyclerView.getAdapter().notifyDataSetChanged();
    }

}

notifyDataSetChanged添加新设备后,不要忘记调用适配器中的方法。


推荐阅读