我遇到一个问题,因为我找不到任何解释。 我有一个使用TabManager显示片段的FragmentActivity,如下所示:
public class WorkOrderFormTabFragmentActivity extends FragmentActivity {
TabHost mTabHost;
TabManager mTabManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.work_order_form_tab_new);
mTabHost = (TabHost)findViewById(android.R.id.tabhost);
mTabHost.setup();
mTabManager = new TabManager(this, mTabHost, R.id.realtabcontent);
mTabManager.addTab(mTabHost.newTabSpec("form").setIndicator("Form"),
WorkOrderFormFragment.class, null);
mTabManager.addTab(mTabHost.newTabSpec("pictures").setIndicator("Pictures"),
PictureListFragment.class, null);
if (savedInstanceState != null) {
mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab"));
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("tab", mTabHost.getCurrentTabTag());
}
public static class TabManager implements TabHost.OnTabChangeListener {
private final FragmentActivity mActivity;
private final TabHost mTabHost;
private final int mContainerId;
private final HashMap<String, TabInfo> mTabs = new HashMap<String, TabInfo>();
TabInfo mLastTab;
static final class TabInfo {
private final String tag;
private final Class<?> clss;
private final Bundle args;
private Fragment fragment;
TabInfo(String _tag, Class<?> _class, Bundle _args) {
tag = _tag;
clss = _class;
args = _args;
}
}
static class DummyTabFactory implements TabHost.TabContentFactory {
private final Context mContext;
public DummyTabFactory(Context context) {
mContext = context;
}
@Override
public View createTabContent(String tag) {
View v = new View(mContext);
v.setMinimumWidth(0);
v.setMinimumHeight(0);
return v;
}
}
public TabManager(FragmentActivity activity, TabHost tabHost, int containerId) {
mActivity = activity;
mTabHost = tabHost;
mContainerId = containerId;
mTabHost.setOnTabChangedListener(this);
}
public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
tabSpec.setContent(new DummyTabFactory(mActivity));
String tag = tabSpec.getTag();
TabInfo info = new TabInfo(tag, clss, args);
info.fragment = mActivity.getSupportFragmentManager().findFragmentByTag(tag);
if (info.fragment != null && !info.fragment.isDetached()) {
FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
ft.detach(info.fragment);
ft.commit();
}
mTabs.put(tag, info);
mTabHost.addTab(tabSpec);
}
@Override
public void onTabChanged(String tabId) {
TabInfo newTab = mTabs.get(tabId);
if (mLastTab != newTab) {
FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
if (mLastTab != null) {
if (mLastTab.fragment != null) {
//ft.detach(mLastTab.fragment);
ft.hide(mLastTab.fragment);
}
}
if (newTab != null) {
if (newTab.fragment == null) {
newTab.fragment = Fragment.instantiate(mActivity,
newTab.clss.getName(), newTab.args);
ft.add(mContainerId, newTab.fragment, newTab.tag);
} else {
//ft.attach(newTab.fragment);
ft.show(newTab.fragment);
}
}
mLastTab = newTab;
ft.commit();
mActivity.getSupportFragmentManager().executePendingTransactions();
}
}
}
在此FragmentActivity的第二个标签中,用户可以管理图片列表并使用相机添加更多图片。
片段代码:
public class PictureListFragment extends Fragment {
static final int TAKE_PICTURE_ACTIVITY = 1;
static final int EDIT_PICTURE_ACTIVITY = 2;
FormPictureListAdapter lvAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup viewgrp,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View cont = inflater.inflate(R.layout.form_picture_list, viewgrp, false);
LinearLayout container = (LinearLayout)cont.findViewById(R.id.formPictureListLayout);
try{
final Context context = getActivity();
ListView ls2 = new ListView(context);
// clear previous results in the LV
ls2.setAdapter(null);
// populate
ArrayList<MFPicture> pictures = new ArrayList<MFPicture>();
//pictures.add(0, new MFPicture());
pictures.addAll(((MFApplication)getActivity().getApplication()).getCurrentForm().getPictures());
lvAdapter = new FormPictureListAdapter(context, pictures);
ls2.setAdapter(lvAdapter);
LinearLayout.LayoutParams Params = new LinearLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT, 0, 1f);
ls2.setLayoutParams(Params);
ls2.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
final MFPicture picture = ((MFPictureView)view).getPicture();
final int idx = position;
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which){
case DialogInterface.BUTTON_POSITIVE:
//Edit picture
EditPictureActivity.setPicture(picture);
Intent configurationOpen = new Intent(getActivity(), EditPictureActivity.class);
startActivityForResult(configurationOpen, EDIT_PICTURE_ACTIVITY);
break;
case DialogInterface.BUTTON_NEGATIVE:
//Delete picture
((MFApplication)getActivity().getApplication()).getCurrentForm().getPictures().remove(idx);
MFUtils.deleteFile(picture.getPath());
lvAdapter.updatePictureList(((MFApplication)getActivity().getApplication()).getCurrentForm().getPictures());
lvAdapter.notifyDataSetChanged();
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(getResources().getString(R.string.wo_bem_regie_list_el_action)).setPositiveButton(getResources().getString(R.string.wo_bem_regie_list_el_edit), dialogClickListener)
.setNegativeButton(getResources().getString(R.string.wo_bem_regie_list_el_delete), dialogClickListener).show();
}
});
container.addView(ls2);
LayoutInflater layoutInflater = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view=layoutInflater.inflate(R.layout.add_btn_bottom,container);
view.setBackgroundResource(R.drawable.list_selector_even);
TextView text = (TextView)view.findViewById(R.id.title);
text.setText(getResources().getString(R.string.wo_picturelist_add));
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v){
v.setBackgroundResource(R.drawable.list_selector_even);
String pictureFile = ((MFApplication)getActivity().getApplication()).getNextPictureFile();
String picPath = MFUtils.MF_STORAGE_PATH+"/"+pictureFile;
Log.e("FormPictureListActivity", "PicturePath : "+picPath);
//setBackgroundResource(android.R.drawable.list_selector_background);
try {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(picPath)));
startActivityForResult(intent, TAKE_PICTURE_ACTIVITY);
} catch (ActivityNotFoundException e) {
Log.e("FormPictureListActivity", "Call failed", e);
}
}
});
}
catch(Exception e){
e.printStackTrace();
Log.e("FormPictureListActivity", "Error:", e);
}
return cont;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
//super.onActivityResult(requestCode, resultCode, data);
String pictureFile = ((MFApplication)getActivity().getApplication()).getPictureFile();
Log.d("FormPictureListActivity", "ActivityResult:"+resultCode);
Log.d("FormPictureListActivity", "ActivityResult-picFile:"+pictureFile);
if (requestCode == TAKE_PICTURE_ACTIVITY){
if(resultCode == getActivity().RESULT_OK){
Log.d("FormPictureListActivity", "ActivityResult:OK");
MFPicture picture = new MFPicture(MFPicture.TYPE_PICTURE, MFUtils.MF_STORAGE_PATH+"/"+pictureFile);
((MFApplication)getActivity().getApplication()).getCurrentForm().getPictures().add(picture);
lvAdapter.updatePictureList(((MFApplication)getActivity().getApplication()).getCurrentForm().getPictures());
lvAdapter.notifyDataSetChanged();
EditPictureActivity.setPicture(picture);
Intent configurationOpen = new Intent(getActivity(), EditPictureActivity.class);
startActivityForResult(configurationOpen, EDIT_PICTURE_ACTIVITY);
}
}
else if (requestCode == EDIT_PICTURE_ACTIVITY){
EditPictureActivity.getPicture().setComment(EditPictureActivity.getPicture().getCommentUIValue());
lvAdapter.updatePictureList(((MFApplication)getActivity().getApplication()).getCurrentForm().getPictures());
lvAdapter.notifyDataSetChanged();
}
}
}
我的测试设备(Nexus 5,Galaxy Nexus,Galaxy Mini 2)上的一切都运行良好,但我不时收到其他无法访问的设备(主要是运行Android 4.0.4的设备)的错误:
java.lang.RuntimeException: Unable to resume activity
{com.mf.mobile.android/com.mf.mobile.android.WorkOrderFormTabFragmentActivity}: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=131073, result=-1, data=null} to activity {com.mf.mobile.android/com.mf.mobile.android.WorkOrderFormTabFragmentActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2616)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2644)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2130)
at android.app.ActivityThread.access$600(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1248)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4645)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:809)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:576)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=131073, result=-1, data=null} to activity {com.mf.mobile.android/com.mf.mobile.android.WorkOrderFormTabFragmentActivity}: java.lang.NullPointerException
at android.app.ActivityThread.deliverResults(ActivityThread.java:3156)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2599)
... 12 more
Caused by: java.lang.NullPointerException
at com.timewise.mobile.android.fragments.PictureListFragment.onActivityResult(PictureListFragment.java:138)
at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:166)
at android.app.Activity.dispatchActivityResult(Activity.java:4662)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3152)
... 13 more
NPE出现在以下代码行中: (((MframeApplication)getActivity()getApplication())getCurrentForm()getPictures()。)lvAdapter.updatePictureList;
这意味着此时lvAdapter变量为null。但是这个变量应该在onCreateView of Fragment中设置...这让我觉得,在某些时候片段可能已经被重新创建而没有调用onCreateView。
我找不到关于这个问题的任何解释。你能帮我解决这个问题吗?
非常感谢
答案 0 :(得分:2)
好吧,我认为如果用户打开您的应用然后点击主页按钮,然后点击显示正在运行的应用程序按钮(主页按钮右侧的按钮)或按住主页,就会发生这种情况某些手机上的按钮,并选择您的应用程序返回它。然后,如果你查看生命周期,它将调用onResume(这是上面的堆栈跟踪中的内容)而不再调用onCreateView。
现在,您应该能够通过进入Nexus 5上的Developer选项并选择Do not keep activities来模仿这一点。然后打开你的应用程序,转到该片段点击主页按钮,然后运行应用程序按钮并选择你的应用程序,我认为它会显示该例外。