首页 > 解决方案 > doInBackground 不在 Activity onCreate 内运行

问题描述

我所拥有的: 我有一个SearchActivity,它从一个片段(单击按钮后)接收一个 ArrayList (NameDesSearch)并更新一个简单的listview。当我单击列表视图项时,单击的列表项的相应对象(orgDesObj)会出现一个新视图。此功能运行良好。

当前接收列表(NameDesSearch)由名称和描述组成。都是字符串。

但是,我只想显示列表名称。因此我尝试创建一个函数(titlefunc())。这里创建了一个新的 ArrayList ( NameDesTitles ) 以仅添加相关名称。

问题: 但是,在我调用 titlefunc() 时,Do In 后台功能似乎无法正常工作。

尝试: 我放了几个Log来捕捉点。我也在单击项目的列表视图中使用相同的函数( getLocDesOb() )。令人惊讶的是它有效,甚至 doInBackground 函数也有效。但是当搜索活动创建并调用 titlefunc()时,doInBackground中的搜索列表 ( finalODescriptionArrayList ) 为空()。形成日志,我收到finalODescriptionArrayList的内容为 [],大小为 0。但是,当我单击列表视图项时finalODescriptionArrayList更新。

我什至也尝试过移出NameDesSearch = getIntent().getStringArrayListExtra("searched");该功能。

似乎我的 doInBackground 方法仅在单击列表项而不是创建活动时调用。其他所有功能都运行良好。我不确定为什么我的titlefunc()被调用,为什么finalODescriptionArrayList没有更新。

我将不胜感激有关此的任何建议。谢谢 !

我的代码:为了清楚起见,我删除了日志。

public class SearchActivity extends AppCompatActivity {

    ListView searchedListView;
    String SearchedWord;
    private ArrayAdapter<String> orgAdapter;
    ArrayList<String> NameDesSearch = new ArrayList<String>();
    ArrayList<String> NameDesTitles = new ArrayList<String>();
    private OService OService;
    ArrayList<ODescription> finalODescriptionArrayList = new ArrayList<ODescription>();

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);
        searchedListView = (ListView) findViewById(R.id.searched_list_view);
        new GetCourse().execute();

        titlefunc();

        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, NameDesTitles);
        searchedListView.setAdapter(arrayAdapter);

        searchedListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String selectedItemText = parent.getItemAtPosition(position).toString();
                ODescription orgDesObj = getLocDesOb(selectedItemText);
                if (orgDesObj != null) {

                    Intent intent = new Intent(SearchActivity.this, View.class);
                    intent.putExtra("sOb", orgDesObj);
                    startActivity(intent);
                }
            }
        });
    }

    @SuppressLint("StaticFieldLeak")
    private class GetCourse extends AsyncTask<Void, Void, Void> {

        @TargetApi(Build.VERSION_CODES.N)
        @Override
        protected Void doInBackground(Void... voids) {
            try {
                finalODescriptionArrayList = JsontoObject.jsonToObjectData(getResources().openRawResource(R.raw.newdb));

            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    public ODescription getLocDesOb(String selectedItemText) {

        if (finalODescriptionArrayList == null) {
            return null;
        }
        for (ODescription locDescObj : finalODescriptionArrayList) {
            if (locDescObj.getName().equals(selectedItemText) || locDescObj.getDescription().equals(selectedItemText)) {
                return locDescObj;
            }
        }
        return null;
    }

    public void titlefunc() {
        NameDesSearch = getIntent().getStringArrayListExtra("searched");
        for (String searchNameDes : NameDesSearch) {
            ODescription orgDesObj2 = getLocDesOb(searchNameDes);
            if (orgDesObj2 != null) {

                NameDesTitles.add(orgDesObj2.getName());
            }
        }
    }
}

使用onPostExecute 更新 AsyncTask下方答案后的尝试。然后因为它需要一点时间,所以添加了一个进度条onPreExecute删除了 oncreate 方法中的titlefunc()

这种方法现在有效。但是,有时也存在同样的问题。到适配器的 Arraylist 为空,因此 listview 为空。似乎仍然需要很多时间来完成后台任务。

更新了 AsyncTask

    @SuppressLint("StaticFieldLeak")
    private class GetCourse extends AsyncTask<Void, Void, Void> {
ProgressDialog progressDialog;

@Override
protected void onPreExecute() {
    super.onPreExecute();
    progressDialog = new ProgressDialog(SearchActivity.this);
    progressDialog.setMessage("Searching");
    progressDialog.setCancelable(false);
    progressDialog.show();
}
        @TargetApi(Build.VERSION_CODES.N)
        @Override
        protected Void doInBackground(Void... voids) {
            try {
                finalODescriptionArrayList = JsontoObject.jsonToObjectData(getResources().openRawResource(R.raw.newdb));

            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
@Override
protected void onPostExecute(Void aVoid) {
    super.onPostExecute(aVoid);
    titlefunc();
    arrayAdapter.notifyDataSetChanged();
    if (progressDialog.isShowing())
        progressDialog.dismiss();
}
   }

修改 titlefunc() - 删除重复项

Set<String > set = new HashSet<>( NameDesTitles);
NameDesTitles.clear();
NameDesTitles.addAll(set);

标签: javaandroidarraylistandroid-activitybackground-process

解决方案


AsyncTask在后台异步运行。当您打电话时(很可能)它不会完成titleFunc()(这就是您所看到的)。

您可以通过多种方式解决此问题。一种方法是在AsyncTask完成后更新适配器的内容。您可以在后台处理完成时调用的其中onPostExecute()执行此操作。AsyncTask在该方法中,您可以运行您的titleFunc()或类似的东西来过滤您想要显示的结果。然后,您需要通过调用来告诉您Adapter更新视图。notifyDatasetChanged()Adapter


推荐阅读