【问题标题】:How to refresh listview in fragment after asynctask finishes?异步任务完成后如何刷新片段中的列表视图?
【发布时间】:2019-01-25 15:35:04
【问题描述】:

应用程序启动时主activity是USNameFragment。这个片段启动 Asynctask 并且在 Asynctask 完成后,他通过接口将结果列表发送回片段。 Fragment 然后在 onDataRetrieved() 中取回这个列表,然后应该显示这个列表。

在 USNameFragment onCreate() 之后,片段列表视图为空。但是 onDataRetrieved() 中的 Toast 表示从 Asynctask 中检索到了 3 个对象。

我确实找到了一个技巧来展示它,但它并没有发挥应有的作用。 列表项仅在配置更改后显示在列表视图中,例如更改设备方向,但在创建片段时不显示。

这里有什么问题?感谢您的建议。

这是我在 Fragment 和 AsyncTask 之间进行通信的接口:

public interface IActivityRef {

void onDataRetrieved(List<USDto> usDtos);
}

这是我实现 IActivityRef 接口的 Fragment:

public class USNameFragment extends Fragment
    implements IActivityRef {

private AsyncTask<String, Void, USResponse> usTask;
private WeakReference<IActivityRef> context;
private ListView listUSNames;
private List<String> usNames;

public USNameFragment() {
    // Required empty public constructor
    usNames = new ArrayList<>();
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);

    this.context = new WeakReference<>((IActivityRef) this);
}

@Override
public void onDetach() {
    super.onDetach();

    context = null;
}

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

    // Retain this fragment across configuration changes.
    setRetainInstance(true);

    usTask = new USTask(this);
    usTask = usTask.execute("params");
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    // Inflate the layout for this fragment
    View rootView = inflater.inflate(R.layout.fragment_us_name, container, false);

    listUSNames = rootView.findViewById(R.id.listUS);
    listUSNames.setAdapter(new ArrayAdapter<String>(
            getActivity(), R.layout.item_us_name, R.id.usName, usNames));

    return rootView;
}

@Override
public void onStop() {
    if (usTask != null && usTask.getStatus() == AsyncTask.Status.RUNNING) {
        usTask.cancel(true);
    }
    usTask = null;

    super.onStop();
}

@Override
public void onDataRetrieved(List<USDto> usDtos) {
    this.usNames = new USColumns().getUSNames(usDtos);
    Toast.makeText(getActivity(), "Data retrieved! List size = " + usDtos.size(),
            Toast.LENGTH_LONG).show();
}


}

这里是异步任务:

public class USTask extends AsyncTask<String, Void, USResponse> {

private WeakReference<IActivityRef> context;
private TwApiClient twApiClient;

public USTask(IActivityRef context) {

    this.context = new WeakReference<>(context);
}

@Override
protected void onPreExecute() {
    super.onPreExecute();
}

@Override
protected USResponse doInBackground(String... params) {

    // do http code here
}

@Override
protected void onPostExecute(USResponse usResponse) {
    super.onPostExecute(usResponse);

    if(context != null && usResponse != null) {
        IActivityRef activity = context.get();
        activity.onDataRetrieved(usResponse.getUS());
    }
}

@Override
protected void onProgressUpdate(Void... values) {
    super.onProgressUpdate(values);
}

}

编辑 认为片段布局是在 onDataRetrieved() 中检索列表之前创建的。也许应该如何刷新列表视图?

EDIT2 问题在于刷新列表视图适配器,而不是从片段发送上下文到异步任务。

【问题讨论】:

    标签: android android-fragments android-asynctask android-context


    【解决方案1】:

    问题在于片段中的 onDataRetrieved() 中的异步任务完成后未更新 ListView 适配器。

    所以解决方案就这么简单:

    将此字段添加到 USNameFragment:

    private ArrayAdapter<String> listAdapter;
    

    然后在 onCreateView() 中初始化这个adapter并赋值给listview:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
    
        // Inflate the layout for this fragment
        View rootView = inflater.inflate(R.layout.fragment_us_name, container, false);
    
        listUSNames = rootView.findViewById(R.id.listUS);
        listAdapter = new ArrayAdapter<String>(
                getActivity(), R.layout.item_us_name, R.id.usName, usNames);
        listUSNames.setAdapter(listAdapter);
    
        return rootView;
    }
    

    然后在 onDataRetrieved() 中重新初始化这个适配器:

    @Override
    public void onDataRetrieved(List<USDto> usDtos) {
        this.usNames = new USColumns().getUSNames(usDtos);
        listAdapter = new ArrayAdapter<String>(
                getActivity(), R.layout.item_us_name, R.id.usName, usNames);
        listUSNames.setAdapter(listAdapter);
    }
    

    还将 asynctask 的开始从 onCreate() 移至 USNameFragment 中的 onAttach():

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
    
        this.context = new WeakReference<>((IActivityRef) this);
        usTask = new USTask(this);
        usTask = usTask.execute("params");
    

    }

    就是这样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-09
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多