Android Fragment 生命周期问题(onActivityResult 上的 NullPointerException)

2023-12-06

我遇到一个问题,我找不到任何解释。 我有一个使用 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 出现在这行代码中: lvAdapter.updatePictureList(((MframeApplication)getActivity().getApplication()).getCurrentForm().getPictures());

这意味着此时lvAdapter变量为null。但是这个变量应该在Fragment的onCreateView中设置...这让我觉得,在某些时候Fragment可能已经在没有调用onCreateView的情况下被重新创建了。

我找不到关于这个问题的任何解释。你能帮我解决这个问题吗?

非常感谢


好的,我认为如果用户打开您的应用程序,然后点击主页按钮,然后点击显示正在运行的应用程序按钮(主页按钮右侧的按钮)或按住某些设备上的主页按钮,就会发生这种情况手机并选择您的应用程序以返回。然后,如果您查看生命周期,它将调用 onResume (这就是上面的堆栈跟踪中的内容),而不会再次调用 onCreateView。

片段生命周期

现在,您应该能够通过进入 Nexus 5 上的“开发者选项”并选择“不保留活动”来模仿这种情况,以查看它的发生。然后打开您的应用程序,转到该片段,点击主页按钮,然后点击正在运行的应用程序按钮并选择您的应用程序,我认为它会向您显示该异常。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android Fragment 生命周期问题(onActivityResult 上的 NullPointerException) 的相关文章

  • Android 主机意图过滤器通配符

    是否可以在 android host 属性上使用通配符 就像是 android host site com android pathPattern android pathPrefix m android scheme http gt Or
  • 使用 APDU 命令的有效 NFC 读取比特率是多少?

    我目前正在使用 Android IsoDep trancieve 函数发送和接收累计 1628 字节的数据 该函数分布在 35 个 APDU 命令 选择应用程序 身份验证 读取 中 字节计数包括返回的 MAC 校验和以及由 transcie
  • AppCompat v21 工具栏更改徽标大小

    我正在从以前的操作栏迁移到 appcompat v21 中的新工具栏功能 我仍然想将徽标保留在操作栏 工具栏 的左上角 为此 我在布局中添加了支持工具栏 并为其创建了一个新的工具栏 app theme style NewToolBarSty
  • 如何使用 adb 在设备上安装现有的 Android 应用程序?

    在开发过程中 我使用类似的东西 adb s 192 168 1 77 5555 uninstall com myApp app adb s 192 168 1 77 5555 install path to android debug ap
  • Google Firebase - 如何删除崩溃报告?

    我最终失明了吗 还是没有明显的方法可以通过 Google Firebase Web 控制台删除 Firebase 崩溃报告 我的 Android 应用程序已成功记录报告 但现在出现大量 开发崩溃 占用了我在控制台中的大部分视图 这使得找到实
  • SQLite (Android):使用 ORDER BY 更新查询

    Android SQLite 我想要在 myTable 中的其他行之间插入行在android中使用SQLite 为此 我尝试增加从第 3 行开始的所有行的 id 这样 我就可以在位置 3 处插入新行 myTable 的主键是列 id 表中没
  • 按钮未显示在屏幕上

    我创建了一个应用程序 其中显示带有图像和文本的列表视图 我在页面末尾添加按钮 但这没有显示在屏幕上 我是 Android 新手 我该如何解决这个问题 这是我的 UI XML 代码
  • 如何使用闹钟音量和 setAudioAttributes 来播放铃声?

    所以我正在尝试了解音频属性 这是我到目前为止所拥有的 alarm getSound will return a proper URI to pick a ringtone Ringtone tone RingtoneManager getR
  • Android-工具栏中的SearchView

    我只想在我的应用程序中添加 searchview 但我不想搜索任何东西 只是我想要用户输入的查询 到目前为止 我尝试了这段代码 但是当我运行我的应用程序时它崩溃了 Update 我尝试了这个 但即使我的应用程序崩溃了 main menu x
  • Android中不同线程的数据库访问

    我有一个在 AsyncTasks 中从互联网下载数据的服务 它解析数据并将其存储在数据库中 该服务持续运行 当服务写入数据库时 活动会尝试从数据库中读取更改 我有一个数据库助手 有多种写入和读取方法 这会导致问题吗 可能尝试从两个不同的线程
  • 获取可以共享数据的应用程序列表

    此代码显示默认共享对话框 Intent sharingIntent new Intent Intent ACTION SEND sharingIntent setType text html sharingIntent putExtra a
  • 从多个选项卡中的编辑文本字段获取文本

    我正在尝试创建一个使用选项卡作为输入表单的 Android 应用程序 基本上 我希望对其进行设置 以便用户可以在一个选项卡上输入一些信息 然后提交该信息 或者转到另一个选项卡并输入更多信息 然后从两个选项卡提交信息 我正在使用操作栏和片段来
  • Android ListView setSelection() 似乎不起作用

    我有一个ListActivity实现onListItemClick 并调用doSomething 类的功能 后者包含l setSelection position where l is the ListView object 现在有一个on
  • 如何从android获取应用程序安装时间

    我尝试了一些方法 但没有成功 请帮助我 PackageManager pm context getPackageManager ApplicationInfo appInfo pm getApplicationInfo app packag
  • Android 改变 ImageView / Bitmap 的颜色

    我需要找到一种方法来改变 Android 中位图的颜色 我需要在我的应用程序中平滑地替换 更改椭圆形图像的颜色 具体取决于int价值 我需要类似的东西myValue 5比改变我的图像的颜色RED and if myValue 322将颜色更
  • 检测 ListView(或 ScrollView)内的滚动位置

    我正在构建一个聊天室应用程序 其中每 X 秒就会轮询一次新事件 每次发生这种情况时 此代码都会使用新数据更新 RoomAdapter ArrayAdapter 的自定义子类 并将其滚动到底部 RoomAdapter adapter Room
  • Android:确定 2.2 及更高版本上的摄像头数量

    我的应用程序需要在 Android 2 2 及更高版本上运行 我需要一种方法来确定可用摄像机的数量 有很多帖子解决了这个问题 但我找不到一个有效的 一种解决方案是简单地检测操作系统版本 任何 2 2 版本的设备都仅限于 1 个摄像头 即使该
  • android:layout_alignParentBottom 在没有显式布局高度作为 ListView 中的行的情况下使用时会被忽略

    当我使用RelativeLayout与任一fill parent or wrap content作为高度和一个指定的元素 android layout alignParentBottom true 它被忽略并在顶部对齐 设置高度Relati
  • 在状态栏下方显示DialogFragment内容

    我试图显示高度和宽度均具有 match parent 的 DialogFragment 但碰巧在顶部 DialogFragment 显示在 StatusBar 下方 DialogFragment 正在应用一些默认值来填充底部 右侧 左侧和顶
  • 通过powershell运行ADB命令

    所以我尝试通过 powershell 脚本运行一些 ADB 命令 这是我正在尝试做的一个简单示例 adb shell echo in adb shell su root echo you are now root ls cd data da

随机推荐