Fragments中的AsyncTask用于执行数据库更新

时间:2016-04-18 15:38:45

标签: android multithreading android-fragments android-asynctask

我有超过10 fragments执行相同类型的任务:

  1. 使用Retrofit
  2. 从服务器检索数据
  3. 启动异步任务以更新数据库(使用ORMLite)
  4. 更新数据库后,从数据库中检索新数据
  5. 通知数据集已在适配器中更改
  6. 我想知道,一旦从服务器检索数据,将更新数据库代码放入我的片段中的AsyncTask内是否无效? 我无法理解在UI线程上运行的内容以及什么不应该作为自己的线程通过AsyncTask

    启动

    这是我的代码:

    private void getLocalIncidentTemplate() {
        mIncidentTemplate.clear();
        mIncidentTemplate.addAll(GenericDAO.getInstance(EntityGroup.class).queryForAll());
        Collections.sort(mIncidentTemplate);
        Log.e(TAG, "Incident Template count:" + mIncidentTemplate.size());
        mListAdapter.notifyDataSetChanged();
        spinner.setVisibility(View.GONE);
    }
    
    private void getRemoteIncidentTemplate() {
        Call<EntityIncident> call = meepServices.getIncidentTemplate();
        call.enqueue(new Callback<EntityIncident>() {
            @Override
            public void onResponse(Call<EntityIncident> call, Response<EntityIncident> response) {
                if (response.isSuccessful()) {
                    new updateIncidentTemplateTask().execute(response.body());
                }
            }
    
            @Override
            public void onFailure(Call<EntityIncident> call, Throwable t) {
                t.getStackTrace();
                Log.e(TAG, t.toString());
                Utils.showToastMessage(getActivity(), "Error retrieving Incidents", true);
            }
    
        });
    }
    
    private class updateIncidentTemplateTask extends AsyncTask<EntityCategories, Void, Boolean> {
    
        @Override
        protected Boolean doInBackground(EntityCategories... params) {
            updateIncidents(params[0]);
            return true;
        }
    
        protected void onPostExecute(Boolean b) {
            getLocalIncidentTemplate();
            spinner.setVisibility(View.GONE);
        }
    }
    

    以下是使用ORMlite的数据库更新:

    private void updateIncident(EntityCategories categories) {
    
        try {
            categories.setId("MobilePlan");
            //Update base categories
            GenericDAO.getInstance(EntityCategories.class).addOrUpdate(categories);
    
            for (EntityCategories.EntityCategory currentCategory : new ArrayList<>(categories.getCategories())) {
    
                if (currentCategory.getmPlans() != null) {
                    for (EntityPlan myPlan : new ArrayList<>(currentCategory.getmPlans())) {
                        EntityPlan oldPlan = GenericDAO.getInstance(EntityPlan.class).queryById(String.valueOf(myPlan.getmId()));
                        myPlan.setCategories(currentCategory);
                        if (oldPlan != null) {
                            if (!myPlan.getmDateModification().equals(oldPlan.getmDateModification())) {
                                GenericDAO.getInstance(EntityPlan.class).addOrUpdate(myPlan);
                            }
                        } else {
                            GenericDAO.getInstance(EntityPlan.class).addOrUpdate(myPlan);
                        }
                    }
    
                } else {
                    continue;
                }
    
                GenericDAO.getInstance(EntityLabel.class).addOrUpdate(currentCategory.getmLabel());
                currentCategory.setCategories(categories);
                GenericDAO.getInstance(EntityCategories.EntityCategory.class).addOrUpdate(currentCategory);
            }
    
        } catch (Exception e) {
            e.printStackTrace();
        }
        Log.d(TAG, "DATA updated");
    }
    

2 个答案:

答案 0 :(得分:2)

对于您的特定情况,您应该使用AsyncTask从后端检索数据并将其放在数据库中。 请记住,AsyncTask有三种主要方法:

    在UI线程上运行的
  • onPreExecute()。当你需要准备需要UI线程(触摸视图和诸如此类的东西)的东西时很有用
  • doInBackGround()这在后台线程上运行
  • onPostExecute()也在UI线程上运行。

onPostExecute()中,您可以通知适配器新数据。

如果我是你,我会使用加载程序获取通知并从数据库中检索数据。因此,完整的链将是一些:

  1. AsyncTask从后端提取数据并将其存储在数据库中
  2. 您的加载程序会收到通知,说明数据库内部发生了更改,并从中提取数据并在您的activity / fragment中调用onLoadFinished()方法
  3. onLoadFinished()将数据传递给视图适配器。
  4. 我还没有详细说明如何实现这一点。我刚刚介绍了整体架构。

答案 1 :(得分:1)

  

我无法理解在UI线程上运行的内容以及不应该作为自己的线程启动的内容

答案简短:

可能阻止UI线程的所有内容(换句话说,可能需要时间)应该在工作线程(线程池或专用线程)上运行 数据库操作和网络请求是应该始终以异步方式运行的操作的典型示例。

在你的情况下,我只是使用ORM来包装与数据库的所有交互,例如ORMlite或你认为更合适的任何其他交互,在这种情况下,你不必关心内部工作并且只为你的通话完成(成功与否)提供回调