Android - 回调后 Fragment 出现 NullPointerException
Android - NullPointerException in Fragment after callback
这是我第一次使用Fragments,我不太了解如何管理它们。在这种情况下,我有两个片段,它们在 FrameLayout 中动态显示,id 为 fragment_place。问题可能出在 fragmentTransaction(addtobackstack / popbackstack)。
在 Fragment2 中,当我在移动设备上按下菜单按钮时,我会显示一个弹出菜单,它第一次按预期工作,但在我返回到上一个片段并 return 现在到片段 2 之后,如果我按下menubutton 我收到以下错误
java.lang.NullPointerException
at android.support.v7.view.menu.MenuBuilder.<init>(MenuBuilder.java:216)
at android.support.v7.widget.PopupMenu.<init>(PopupMenu.java:103)
at android.support.v7.widget.PopupMenu.<init>(PopupMenu.java:78)
at android.support.v7.widget.PopupMenu.<init>(PopupMenu.java:63)
at package.Fragment2.showPopup(Fragment2.java:93)
下面是 mainactivity 和 fragment2 的代码,这让我抓狂,任何帮助将不胜感激。
public class MainActivity extends AppCompatActivity implements Fragment1.onEvent {
Fragment1 frag;
Fragment2 frag2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
frag = new Frag1();
// Begin the transaction
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_place, frag);
ft.commit();
}
@Override
public void onEventSelected(String key) {
frag2 = new Frag2();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_place,frag2);
ft.addToBackStack(null);
ft.commit();
}
@Override
public void onBackPressed(){
FragmentManager ft = getSupportFragmentManager();
if (ft.getBackStackEntryCount() > 0) {
ft.popBackStack();
} else {
super.onBackPressed();
}
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
int action = event.getAction();
int keyCode = event.getKeyCode();
switch (keyCode) {
case KeyEvent.KEYCODE_MENU:
if (action == KeyEvent.ACTION_UP) {
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_place);
if (f instanceof Fragment2) {
sendBroadcast();
}
}
return true;
default:
return super.dispatchKeyEvent(event);
}
}
private void sendBroadcast(){
Intent intent = new Intent("popup_menu");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}}
这是有问题的片段。错误行基本上是方法 showPopup
public class Fragment2 extends Fragment {
private String key;
private View view;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment, parent, false);
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mMessageReceiver,
new IntentFilter("popup_menu"));
return view;
}
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
showPopup(view);
}
};
public void showPopup(View v) {
Button b = (Button) view.findViewById(R.id.b_attach);
PopupMenu popup = new PopupMenu(getActivity(), b);
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
//dosomething
}
});
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.menu_popup, popup.getMenu());
popup.show();
}}
这是我的做法,对我很有效:
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame,new fragment() ).commit();
我解决了摆脱 sendbroadcast() 和 broadcastReceiver() 的问题,现在我在需要时直接从 mainActivity 调用 showPopup()。
这是我第一次使用Fragments,我不太了解如何管理它们。在这种情况下,我有两个片段,它们在 FrameLayout 中动态显示,id 为 fragment_place。问题可能出在 fragmentTransaction(addtobackstack / popbackstack)。
在 Fragment2 中,当我在移动设备上按下菜单按钮时,我会显示一个弹出菜单,它第一次按预期工作,但在我返回到上一个片段并 return 现在到片段 2 之后,如果我按下menubutton 我收到以下错误
java.lang.NullPointerException
at android.support.v7.view.menu.MenuBuilder.<init>(MenuBuilder.java:216)
at android.support.v7.widget.PopupMenu.<init>(PopupMenu.java:103)
at android.support.v7.widget.PopupMenu.<init>(PopupMenu.java:78)
at android.support.v7.widget.PopupMenu.<init>(PopupMenu.java:63)
at package.Fragment2.showPopup(Fragment2.java:93)
下面是 mainactivity 和 fragment2 的代码,这让我抓狂,任何帮助将不胜感激。
public class MainActivity extends AppCompatActivity implements Fragment1.onEvent {
Fragment1 frag;
Fragment2 frag2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
frag = new Frag1();
// Begin the transaction
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_place, frag);
ft.commit();
}
@Override
public void onEventSelected(String key) {
frag2 = new Frag2();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_place,frag2);
ft.addToBackStack(null);
ft.commit();
}
@Override
public void onBackPressed(){
FragmentManager ft = getSupportFragmentManager();
if (ft.getBackStackEntryCount() > 0) {
ft.popBackStack();
} else {
super.onBackPressed();
}
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
int action = event.getAction();
int keyCode = event.getKeyCode();
switch (keyCode) {
case KeyEvent.KEYCODE_MENU:
if (action == KeyEvent.ACTION_UP) {
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_place);
if (f instanceof Fragment2) {
sendBroadcast();
}
}
return true;
default:
return super.dispatchKeyEvent(event);
}
}
private void sendBroadcast(){
Intent intent = new Intent("popup_menu");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}}
这是有问题的片段。错误行基本上是方法 showPopup
public class Fragment2 extends Fragment {
private String key;
private View view;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment, parent, false);
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mMessageReceiver,
new IntentFilter("popup_menu"));
return view;
}
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
showPopup(view);
}
};
public void showPopup(View v) {
Button b = (Button) view.findViewById(R.id.b_attach);
PopupMenu popup = new PopupMenu(getActivity(), b);
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
//dosomething
}
});
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.menu_popup, popup.getMenu());
popup.show();
}}
这是我的做法,对我很有效:
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame,new fragment() ).commit();
我解决了摆脱 sendbroadcast() 和 broadcastReceiver() 的问题,现在我在需要时直接从 mainActivity 调用 showPopup()。