如何将昂贵的模拟移动到异步任务?

时间:2013-05-24 08:32:08

标签: android

我有FragmentActivity,其中包含ViewPagerActionBar。这个ViewPager有一个带有3个片段的适配器。这些片段会根据TextView中选择的项目更改其ActionBar的值。

这是我的问题:每当我在ViewPager中的视图之间滑动时,我希望根据ActionBar中选择的项目设置片段的数据。我通过设置一个监听器来尝试这个:

    mViewPager.setOnPageChangeListener(new OnPageChangeListener() {

        @Override
        public void onPageSelected(int arg0) 
        {
            setTimePeriod(actionBarItemPosition);
        }
    }

然后,setTimePeriod()调用两种模拟方法:getComparedUsage()getThisUsage()。其中每个都在CPU负载上很重,因此当在视图之间滑动时,我的 UI非常滞后

我该如何解决这个问题?

private void setTimePeriod(int position)
{
    periodDropDownPosition = position;

    // Get a reference to the active fragment currently shown by the ViewPager.
    currentFragment = (DetailedFragment) mMyFragmentPagerAdapter.getItem(mViewPager.getCurrentItem());
    List<UsageEntry> dataSet = currentFragment.getDataSet();

    setViewReferencessOnActiveFragment(currentFragment);

    differenceTextView = (TextView) activeView.findViewById(R.id.usage_results_total_value_tv);
    try
    {
        switch(position)
        {
        case PERIOD_DAY:
            resultsThisTextView.setText(R.string.compared_to_text_this_day);
            resultsComparedToTextView.setText(R.string.compared_to_text_compared_day);  
            comparedUsage = getComparedUsage(PERIOD_DAY, dataSet); 
                        // This call brings the phone to its knees
            thisUsage = getThisUsage(PERIOD_DAY, dataSet); 
                        // This call brings the phone to its knees
            break;
        case PERIOD_WEEK:
            resultsThisTextView.setText(R.string.compared_to_text_this_week);
            resultsComparedToTextView.setText(R.string.compared_to_text_compared_week);         
            comparedUsage = getComparedUsage(PERIOD_WEEK, dataSet);
                        // This call brings the phone to its knees
            thisUsage = getThisUsage(PERIOD_WEEK, dataSet);
                        // This call brings the phone to its knees
            break;
        case PERIOD_MONTH:
            resultsThisTextView.setText(R.string.compared_to_text_this_month);
            resultsComparedToTextView.setText(R.string.compared_to_text_compared_month);
            comparedUsage = getComparedUsage(PERIOD_MONTH, dataSet); 
                        // This call brings the phone to its knees
            thisUsage = getThisUsage(PERIOD_MONTH, dataSet); 
                        // This call brings the phone to its knees
            break;
        case PERIOD_YEAR:
            resultsThisTextView.setText(R.string.compared_to_text_this_year);
            resultsComparedToTextView.setText(R.string.compared_to_text_compared_year);
            comparedUsage = getComparedUsage(PERIOD_YEAR, dataSet); 
                        // This call brings the phone to its knees
            thisUsage = getThisUsage(PERIOD_YEAR, dataSet); 
                        // This call brings the phone to its knees
            break;
        }

        setCashOrUnits(isInCashMode);

    }catch(NotEnoughDataException e)
    {
        noDataLayout = (RelativeLayout)activeView.findViewById(R.id.results_not_enough_data_view);
        noDataLayout.setVisibility(View.VISIBLE);
        resultsView = (RelativeLayout)activeView.findViewById(R.id.results_view);
        resultsView.setVisibility(View.INVISIBLE);
        e.printStackTrace();
    }catch(NullPointerException e)
    {
        noDataLayout = (RelativeLayout)activeView.findViewById(R.id.results_not_enough_data_view);
        noDataLayout.setVisibility(View.VISIBLE);
        resultsView = (RelativeLayout)activeView.findViewById(R.id.results_view);
        resultsView.setVisibility(View.INVISIBLE);
        e.printStackTrace();
    }
}

1 个答案:

答案 0 :(得分:0)

你可能想要一个AsyncTask

AsyncTask将允许您在后台运行慢速操作(另一个线程),然后在完成后执行一些UI代码,以更新显示。虽然运行缓慢,但您的设备似乎不会完全没有响应。

AsyncTask子类(将是您在上面显示的类中的内部类):

private class UsageTask extends AsyncTask<Integer, Void, Boolean> {

     private List<UsageEntry> dataSet;

     public UsageTask(List<UsageEntry> data) {
         this.dataSet = data;
     }

     protected Boolean doInBackground(Integer... params) {
         Boolean success = Boolean.TRUE;
         int period = params[0];
         try {
             // I'm assuming these two methods can throw the exceptions?
             comparedUsage = getComparedUsage(period, dataSet); 
             thisUsage = getThisUsage(period, dataSet);
         } catch(NotEnoughDataException e) {
             success = Boolean.FALSE; 
             e.printStackTrace();
         } catch(NullPointerException e) {
             success = Boolean.FALSE; 
             e.printStackTrace();
         } 
         return success;
     }

     protected void onPostExecute(Boolean success) {
         if (success) {
            // I'm assuming this call somehow modifies the UI?
            setCashOrUnits(isInCashMode);
         } else {
            noDataLayout = (RelativeLayout)activeView.findViewById(R.id.results_not_enough_data_view);
            noDataLayout.setVisibility(View.VISIBLE);
            resultsView = (RelativeLayout)activeView.findViewById(R.id.results_view);
            resultsView.setVisibility(View.INVISIBLE);
         }
     }
 }

然后像这样使用它:

private void setTimePeriod(int position)
{
    periodDropDownPosition = position;

    // Get a reference to the active fragment currently shown by the ViewPager.
    currentFragment = (DetailedFragment) mMyFragmentPagerAdapter.getItem(mViewPager.getCurrentItem());
    List<UsageEntry> dataSet = currentFragment.getDataSet();

    setViewReferencessOnActiveFragment(currentFragment);

    differenceTextView = (TextView) activeView.findViewById(R.id.usage_results_total_value_tv);

    switch(position)
    {
        case PERIOD_DAY:
            resultsThisTextView.setText(R.string.compared_to_text_this_day);
            resultsComparedToTextView.setText(R.string.compared_to_text_compared_day);
            break;  
        case PERIOD_WEEK:
            resultsThisTextView.setText(R.string.compared_to_text_this_week);
            resultsComparedToTextView.setText(R.string.compared_to_text_compared_week);         
            break;
        case PERIOD_MONTH:
            resultsThisTextView.setText(R.string.compared_to_text_this_month);
            resultsComparedToTextView.setText(R.string.compared_to_text_compared_month);
            break;
        case PERIOD_YEAR:
            resultsThisTextView.setText(R.string.compared_to_text_this_year);
            resultsComparedToTextView.setText(R.string.compared_to_text_compared_year);
            break;
        default: 
            return;
            break;
    }

    UsageTask task = new UsageTask(dataSet);
    task.execute(position);
}

注意:在文本视图中设置文本时,我不确切知道UI的样子,如上面的switch-case语句所示。您可能不希望在慢速操作完成后 之前更改这些内容。如果是这样,只需将它们移至onPostExecute()

此外,在慢速操作开始之前显示某种进度指示器可能是一种很好的做法,让用户知道发生了什么。您可以在创建任务之前,setTimePeriod()中执行此操作,或在UsageTask类中实现onPreExecute(),并将其放在那里。停止onPostExecute()中的进度指示器。