我有一个带导航抽屉的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;它允许阻止片段被加载两次(或更多),但它不会阻止我的应用程序在我第一次显示时滞后。这就是为什么我尝试在应用程序启动时加载所有片段(使用启动画面或其他东西)以防止进一步滞后。
感谢您的帮助/建议。
答案 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方法并重写堆栈逻辑。