Adr*_*nzi 7 android android-fragments navigation-drawer
我正在处理的Android应用程序只有一个MainActivity,应用程序的每个屏幕都实现为Fragment.每个片段在MainActivity中实例化为私有类变量:
public class MainActivity extends Activity implements MainStateListener {
private FragmentManager fm = getFragmentManager();
private BrowseFragment browseFragment = BrowseFragment.newInstance();
...
Run Code Online (Sandbox Code Playgroud)
有一个"片段帧"可以加载每个屏幕片段.在应用程序中切换屏幕时,会调用此代码来加载片段:
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.frag_frame, incoming);
ft.addToBackStack(null);
ft.commit();
fm.executePendingTransactions();
Run Code Online (Sandbox Code Playgroud)
每个屏幕片段都有一个监听器,使片段能够调用MainActivity中的各种方法:
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mainStateListener = (MainStateListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement MainStateListener");
}
}
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是从MainActivity中退出的导航抽屉更新片段的一个方面.导航抽屉必须更新片段,并使用此代码执行此操作:
navigationDrawer.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
browseFragment.doSomethingOnBrowserFragment();
}
});
Run Code Online (Sandbox Code Playgroud)
在您更改方向之前,情况正常.然后当前屏幕片段加载正常(browseFragment).但是当你单击导航抽屉导致doSomethingOnBrowserFragment()方法执行时,由于mainStateListener对象本身(在browseFragment中附加)为null,我得到一个空指针异常.根据我对Fragment生命周期的了解,这个变量不应该为null,因为onAttach()方法首先执行任何操作并设置mainStateListener变量.此外,如果我在该browserFragment上有一个使用mainStateListener对象的按钮(在方向更改后),单击该按钮永远不会出现此空指针问题.
堆栈跟踪:
08-04 16:23:28.937 14770-14770/co.openplanit.totago E/AndroidRuntime? FATAL EXCEPTION: main
Process: co.openplanit.totago, PID: 14770
java.lang.NullPointerException
at co.openplanit.totago.MapFragment.enableOfflineMode(MapFragment.java:489)
at co.openplanit.totago.MainActivity.setMapMode(MainActivity.java:663)
at co.openplanit.totago.MainActivity.itineraryMapDrawerSelectItem(MainActivity.java:610)
at co.openplanit.totago.MainActivity.access$200(MainActivity.java:52)
at co.openplanit.totago.MainActivity$5.onItemClick(MainActivity.java:420)
at android.widget.AdapterView.performItemClick(AdapterView.java:299)
at android.widget.AbsListView.performItemClick(AbsListView.java:1158)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:2957)
at android.widget.AbsListView$3.run(AbsListView.java:3850)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:606)
at dalvik.system.NativeStart.main(Native Method)
Run Code Online (Sandbox Code Playgroud)
在我看来,问题可能是使用导航抽屉实际上是与browseFragment生命周期交互并导致它分离或什么.
任何关于如何解决这个问题的建议都将非常感激.
我认为可能发生的情况是,您的活动的 browserFragment 可能与片段管理器显示的 BrowseFragment 不同(如果您单击该片段中的按钮,它似乎工作正常,正如您所说)。
在旋转时,活动将为您的 browserFragment 变量创建一个新的 BrowseFragment 实例(未附加到活动) -每次创建活动时都会运行private BrowseFragment browserFragment = BrowseFragment.newInstance(),但片段管理器将重用现有的您的变量未指向的 BrowseFragment 实例。重用的 BrowseFragment 将被附加并运行该代码来更新 mainStateListener,未使用的新 browserFragment 将不会附加到活动,除非您运行添加它的fragmentTransaction - 因此其中的 mainStateListener 将为 null(未初始化)。
您最好使用片段标签并根据片段管理器中的标签获取片段,而不是创建片段并将其存储在变量中,然后在旋转后尝试访问该变量。
IE
private static final String BROWSE_TAG = "browseFrag";
ft.replace(R.id.frag_frame, browseFragment, BROWSE_TAG);
navigationDrawer.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Fragment browseFragment = fm.findFragmentByTag(BROWSE_TAG);
if (browseFragment != null) {
browseFragment.doSomethingOnBrowserFragment();
}
}
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
979 次 |
| 最近记录: |