在应用启动时预加载一些片段

时间:2015-04-07 21:42:21

标签: android fragment navigation-drawer

我有一个带导航抽屉的Android应用程序。我的问题是一些片段需要几秒钟才能加载(解析器,Map API)。我想在应用程序启动时加载我的所有片段。

我不确定它是否可行或是一种好方法,但我想在主要活动的onCreate方法中创建每个片段的实例。然后,当用户在导航抽屉中选择片段时,我使用现有实例而不是创建新实例。

问题是它在第一次显示特定片段时不会阻止延迟。在我看来,原因是片段构造函数没有做很多操作。

搜索网络后,我无法找到一种优雅的方式来预先加载"应用程序启动时的片段(当用户在抽屉中选择项目时)。

有些帖子谈到AsyncTask,但看起来MapFragment操作不能在主线程中执行(我尝试时遇到异常:java.lang.IllegalStateException:不在主线程上)。 / p>

这是我到目前为止所尝试的内容:

mFragments = new Fragment[BasicFragment.FRAGMENT_NUMBER];
mFragments[BasicFragment.HOMEFRAGMENT_ID] = new HomeFragment();
mFragments[BasicFragment.CAFEFRAGMENT_ID] = new CafeFragment();
mFragments[BasicFragment.SERVICEFRAGMENT_ID] = new ServiceFragment();
mFragments[BasicFragment.GOOGLEMAPFRAGMENT_ID] = new GoogleMapFragment();

在导航栏中选择项目时:

private void selectItem(int position) {

    Fragment fragment = mFragments[position];

    // here, I check if the fragment is null and instanciate it if needed

    FragmentManager fragmentManager = getFragmentManager();
    FragmentTransaction ft = fragmentManager.beginTransaction();
    ft.replace(R.id.content_frame, fragment);
    ft.commit();

    mDrawerList.setItemChecked(position,true);
    mDrawerLayout.closeDrawer(mDrawerList);
}

我也试过this solution;它允许阻止片段被加载两次(或更多),但它不会阻止我的应用程序在我第一次显示时滞后。这就是为什么我尝试在应用程序启动时加载所有片段(使用启动画面或其他东西)以防止进一步滞后。

感谢您的帮助/建议。

3 个答案:

答案 0 :(得分:1)

您可以做的一件事是在null中返回Fragment#onCreateView(),将资源加载到无UI片段中。您也可以调用Fragment#setRetainInstance(true)以防止碎片被破坏。

这可以添加到Activity#onCreate()中的FragmentManager中。从那里,您添加的片段可以挂钩到此资源片段以获取所需的资源。

这样的事情:

public class ResourceFragment extends Fragment {
   public static final String TAG = "resourceFragment";

   private Bitmap mExtremelyLargeBitmap = null;

   @Override
   public View onCreateView(ViewInflater inflater, ViewGroup container, Bundle savedInstanceState) {
     return null;
  }

  @Override
  public void onStart() {
     super.onStart();
     new BitmapLoader().execute();
  }

  public Bitmap getExtremelyLargeBitmap() {
     return mExtremelyLargeBitmap;
  }

  private class BitmapLoader extends AsyncTask<Void, Void, Bitmap> {
      @Override
      protected Bitmap doInBackground(Void... params) {
          return decodeBitmapMethod();
      }

      @Override
      protected void onPostExecute(Bitmap result) {
          mExtremelyLargeBitmap = result;
      }
  }
}

首先将它添加到Activity中的片段管理器中。然后,每当你加载其他片段时,他们只需要从片段管理器中获取资源片段,如下所示:

public class FakeFragment extends Fragment {

   @Override
   public View onCreateView(ViewInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final ResourceFragment resFragment = getFragmentManager().findFragmentByTag(ResourceFragment.TAG);
        Bitmap largeBitmap = resFragment.getBitmap();
        if (largeBitmap != null) {
            // Do something with it.
        }
   }
}

您可能必须设置“注册/取消注册”侦听器,因为您仍需要等待资源加载,但您可以尽快开始加载资源,而不会首先创建一堆片段。

答案 1 :(得分:0)

要预加载片段,可以使用attach()。因此,在OP的情况下,它将是:

ft.attach(fragment).commit();

确保将片段存储在某处并在下次调用ft.replace()时使用该片段。

答案 2 :(得分:0)

您可以将您的片段放在ViewPager中。它默认预加载2页(片段)。您还可以增加预加载页面(片段)的数量

mViewPager.setOffscreenPageLimit(int numberOfPreloadedPages);

但是,您需要重写showFragment方法并重写堆栈逻辑。