显示片段时启动asynctask

时间:2014-07-24 18:33:01

标签: android sqlite android-fragments android-asynctask

我有3个片段。

在每个片段的onActivityCreated()中,我执行异步任务。

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

    mTaskGetPoints = new AsyncTaskGetFavouritePoints();
    mTaskGetPoints.execute();
}

doInBackground中的异步任务从SQLite DB获取数据并创建对象的ArrayList。在onPostExecute中,我调用一个方法在listView上显示数据。

每个片段都有自己的asynctask。

当我"启动" FragmentActivity显示片段1并执行其asynctask。但它最近的片段(片段2,中间片段)也会启动其AsyncTask。

我想知道是否可以仅在用户看到片段时才启动异步任务。 我想如果可能,因为我想显示一个进度对话框(获取数据......)。 现在我从数据库中获取的数据很少,但如果我有很多数据,我想显示进度对话框。现在,如果我在每个asynctask的onPreExecute中显示ProgressDialog,如果从Fragment 1更改为Fragment 2,我在Fragment 2上看到Fragment 3的ProgressDialog:/

也许我错了,使用asynctasks很糟糕。

编辑1: FragmentActivity

public class FragmentActivityInterestPoints extends FragmentActivity implements
        ActionBar.TabListener { 
    PagerAdapterInterestPoints mInterestPointsPagerAdapter;
    ViewPager mViewPager;

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

        setContentView(R.layout.pager_adapter_fragment);
        // Set up the action bar.
        final ActionBar actionBar = getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        // Create the adapter that will return a fragment for each of the three
        // primary sections of the app.
        mInterestPointsPagerAdapter = new PagerAdapterInterestPoints(
                getSupportFragmentManager());

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mInterestPointsPagerAdapter);

        // When swiping between different sections, select the corresponding
        // tab. We can also use ActionBar.Tab#select() to do this if we have
        // a reference to the Tab.
        mViewPager
                .setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
                    @Override
                    public void onPageSelected(int position) {
                        actionBar.setSelectedNavigationItem(position);
                    }
                });

        // For each of the sections in the app, add a tab to the action bar.
        for (int i = 0; i < mInterestPointsPagerAdapter.getCount(); i++) {
            // Create a tab with text corresponding to the page title defined by
            // the adapter. Also specify this Activity object, which implements
            // the TabListener interface, as the callback (listener) for when
            // this tab is selected.
            actionBar.addTab(actionBar.newTab()
                    .setText(mInterestPointsPagerAdapter.getPageTitle(i))
                    .setTabListener(this));
        }

    }


    @Override
    public void onTabSelected(ActionBar.Tab tab,
            FragmentTransaction fragmentTransaction) {
        mViewPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(ActionBar.Tab tab,
            FragmentTransaction fragmentTransaction) {
    }

    @Override
    public void onTabReselected(ActionBar.Tab tab,
            FragmentTransaction fragmentTransaction) {
    }

}


public class PagerAdapterInterestPoints extends FragmentPagerAdapter {

    private static final int PAGES = 3;

    private ArrayList<Fragment> pages = new ArrayList<Fragment>(PAGES);

    public PagerAdapterInterestPoints(FragmentManager fm) {
        super(fm);

        pages.add(new FragmentShowPoints());
        pages.add(new FragmentCategoryPoints());
        pages.add(new FragmentFavouritePoints());
    }

    @Override
    public int getCount() {
        // Show total pages.
        return PAGES;
    }

    @Override
    public Fragment getItem(int position) {
        return pages.get(position);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
        case 0:
            return "Fragment 1";
        case 1:
            return "Fragment 2";
        case 2:
            return "Fragment 3";
        default:
            return "Undefined";
        }
    }

}


public class FragmentShowPoints extends ListFragment {
    private MyDatabase myDB;

    private ArrayList<PointInterest> listPoints = null;
    // UI
    private ListView lv;
    View rootView;
    ListAdapterShowPoints adapter;

    AsyncTaskGetPoints mTaskGetPoints;
    ProgressDialog progressDialog;
    private Activity act;

    public FragmentShowPoints() {

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.activity_show_points, container,
                false);

        this.act = getActivity();

        return rootView;
    }

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

        // Load UI
        lv = getListView();
    }

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

        mTaskGetPoints = new AsyncTaskGetPoints();
        mTaskGetPoints.execute();
    }

    @Override
    public void onPause() {
        if (mTaskGetPoints != null) {
            mTaskGetPoints.cancel(true);
        }
        super.onPause();
    }

    @Override
    public void onDestroy() {
        if (mTaskGetPoints != null) {
            mTaskGetPoints.cancel(true);
        }
        super.onDestroy();
    }


    @Override
    public void onStop() {
        super.onStop();
    }

    private void showPoints() { 
            adapter = new ListAdapterShowPoints(act, listPoints, act);
            setListAdapter(adapter);
        }
    }

    private class AsyncTaskGetPoints extends
            AsyncTask<Void, Void, ArrayList<PointInterest>> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            progressDialog = new ProgressDialog(act);
            progressDialog.setMessage("Loading...");
            progressDialog.show();
        }

        @Override
        protected ArrayList<PointInterest> doInBackground(Void... params) {
            myDB = new MyDatabase(act);
            Cursor c = myDB.getPoints();
            //loop with data
            c.close();
            myDB.close();
            return listPoints;
        }

        @Override
        protected void onPostExecute(ArrayList<PointInterest> result) {
            progressDialog.dismiss();
            showPoints();
        }

    }
}



<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/pager"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".MainActivity" >
</android.support.v4.view.ViewPager>

编辑2(我的解决方案): 我用了一些更简单的东西。

在每个片段的布局中,我在内部添加了另一个布局,其中包含进度条和文本视图。在onResume中,我隐藏了listView并使用进度条和文本视图显示布局。我也在asynctask的onPreexecute中做同样的事情(我认为只有在这一点上应该没问题,因为在onResume中我启动了asynctask(但我正在测试哈哈))。在postExecute中,如果我有数据要显示我隐藏进度条和textview,我会显示列表视图。 重要的是在UI线程中执行此操作,如果不是,我会收到下一个错误:“只有创建视图层次结构的原始线程才能触及其视图。”

getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    // lv.setVisibility(View.VISIBLE);
                    if (listPointsSearch == null) {
                        adapter = new ListAdapterShowPoints(act, listPoints,
                                act);
                    } else {
                        adapter = new ListAdapterShowPoints(act,
                                listPointsSearch, act);
                    }
                    adapter.setActivity(act);

                    setListAdapter(adapter);

                    lv.setVisibility(View.VISIBLE);
                    pRelativeLayout.setVisibility(View.GONE);
                }
            });

但只有我在onPostExecute()中遇到问题。当片段恢复但你没有看到它时,它可以正常工作,我不知道为什么,因为onPreExecute应该崩溃。

编辑3:我也应该使用加载器而不是asynctasks进行测试。

1 个答案:

答案 0 :(得分:0)

问题在于,取决于你用什么来改变你的碎片(从你所说的,我认为你使用的是ViewPager,不是吗?),它会在显示它们之前缓存片段对于用户来说,加载UI并不会很长。

我会说你最好使用片段更改时调用的回调启动AsyncTask。您可以拥有一个由Fragments实现的接口,并在您从一个片段更改为新片段时调用。

修改:您的代码中的更多信息

首先,创建一个由Fragments实现的简单回调接口,它将启动AsyncTask。

public interface OnFragmentShownListener {
    void onFragmentShown();
}

然后,在SimpleOnPageChangeListener#onPageSelected上,致电mInterestPointsPagerAdapter.getItem(position)以检索显示的片段。

然后,仍然在你的onPageSelected中,你调用你的((OnFragmentShownListener) fragment).onFragmentShown(),它应该启动你的AsyncTask。

希望这会有所帮助:)