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

Dav*_*idL 5 android fragment navigation-drawer

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

我不确定是否有可能或一种好的方法来做到这一点,但我正在考虑在主要活动的 onCreate 方法中为我的每个片段创建一个实例。然后,当用户在导航抽屉中选择一个片段时,我使用现有实例而不是创建一个新实例。

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

在网上搜索后,我找不到在应用程序启动时(而不是在用户选择抽屉中的项目时)“预加载”片段的优雅方式。

一些帖子谈到了 AsyncTask,但看起来 MapFragment 操作除了在主线程中无法执行(我尝试时出现异常:java.lang.IllegalStateException: Not on the main thread)。

这是我到目前为止尝试过的:

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();
Run Code Online (Sandbox Code Playgroud)

当在导航抽屉中选择一个项目时:

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);
}
Run Code Online (Sandbox Code Playgroud)

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

感谢您的帮助/建议。

Dee*_*eeV 1

null您可以做的一件事是通过返回in来加载无 UI 片段中的资源Fragment#onCreateView()。您还可以调用Fragment#setRetainInstance(true)以防止片段被破坏。

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

所以像这样:

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;
      }
  }
}
Run Code Online (Sandbox Code Playgroud)

首先将其添加到 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.
        }
   }
}
Run Code Online (Sandbox Code Playgroud)

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