java - 使用工具栏向上箭头导航会重新启动应用程序,但 Android 内置箭头按钮可以工作

标签 java android android-fragments android-lifecycle

请帮忙。

编辑以提出更简单直接的问题

我有三个 Activity (A、B 和 C),每个 Activity 都托管一个 fragment 。 从 fragment C 导航到 fragment B 时,工具栏上的向上箭头导航不起作用。但是,使用内置 Android 后退箭头导航可以正常工作。

将下面生命周期方法的日志记录与两种不同的后退导航进行比较,为什么它会被工具栏后退导航破坏、分离和重新创建(由于参数包为空而崩溃并重新启动应用程序),而在内置的 Android 后退导航上却直接从停止到开始?

工具栏向上箭头上的 Activity 和 fragment 生命周期的顺序

11-30 19:41:15.491 2070-2086/? I/PgedBinderListener: kstate callback type:16 value1=1433 value2=CALLED
11-30 19:41:15.537 13374-13374/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onCreate Called
11-30 19:41:15.541 13374-13374/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onCreateView Called
11-30 19:41:15.607 13374-13374/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onDestroyView Called
11-30 19:41:15.607 13374-13374/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onStart Called
11-30 19:41:15.607 13374-13374/com.navsaria.keeran.clinicbook I/child_details_activity: onStart() called
11-30 19:41:15.607 13374-13374/com.navsaria.keeran.clinicbook I/child_details_activity: onResume() called
11-30 19:41:15.607 13374-13374/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onResume Called
11-30 19:41:17.321 13374-13374/com.navsaria.keeran.clinicbook I/child_details_activity: onPause() called
11-30 19:41:17.878 13374-13374/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onStopCalled
11-30 19:41:17.878 13374-13374/com.navsaria.keeran.clinicbook I/child_details_activity: onStop() called
11-30 19:41:18.838 13374-13374/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onDestroyView Called
11-30 19:41:18.839 13374-13374/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onDestroy Called
11-30 19:41:18.839 13374-13374/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onDetached Called
11-30 19:41:18.839 13374-13374/com.navsaria.keeran.clinicbook I/child_details_activity: onDestroy() called
11-30 19:41:18.874 13374-13374/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onCreate Called

带有 Android 内置后退箭头的 Activity 和 Fragment 生命周期的顺序

12-02 22:31:10.355 16037-16037/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onCreate Called
12-02 22:31:10.357 16037-16037/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onCreateView Called
12-02 22:31:10.420 16037-16037/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onDestroyView Called
12-02 22:31:10.420 16037-16037/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onStart Called
12-02 22:31:10.420 16037-16037/com.navsaria.keeran.clinicbook I/child_details_activity: onStart() called
12-02 22:31:10.421 16037-16037/com.navsaria.keeran.clinicbook I/child_details_activity: onResume() called
12-02 22:31:10.421 16037-16037/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onResume Called
12-02 22:31:13.499 16037-16037/com.navsaria.keeran.clinicbook I/child_details_activity: onPause() called
12-02 22:31:14.122 16037-16037/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onStopCalled
12-02 22:31:14.122 16037-16037/com.navsaria.keeran.clinicbook I/child_details_activity: onStop() called
12-02 22:31:27.380 16037-16037/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onStart Called
12-02 22:31:27.380 16037-16037/com.navsaria.keeran.clinicbook I/child_details_activity: onStart() called
12-02 22:31:27.380 16037-16037/com.navsaria.keeran.clinicbook I/child_details_activity: onResume() called
12-02 22:31:27.380 16037-16037/com.navsaria.keeran.clinicbook I/ChildDetailsFragment: onResume Called

举办 Activity 的抽象类

public abstract class SingleFragmentActivity extends AppCompatActivity {

    protected abstract Fragment createFragment();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment);

        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment = fm.findFragmentById(R.id.fragment_container);

        if (fragment == null) {
            fragment = createFragment();
            fm.beginTransaction()
                    .add(R.id.fragment_container, fragment)
                    .commit();
        }
    }


}

Activity B

public class ChildDetailsActivity extends SingleFragmentActivity {

    public static final String EXTRA_CHILD_ID =
            "com.navsaria.keeran.clinicbook.child_id";
    public static final String TAG = "child_details_activity";

    public static Intent newIntent(Context packagedContext, UUID childId) {
        Intent intent = new Intent(packagedContext, ChildDetailsActivity.class);
        intent.putExtra(EXTRA_CHILD_ID, childId);
        return intent;
    }

    @Override
    protected Fragment createFragment() {
        UUID childId = (UUID) getIntent().getSerializableExtra(EXTRA_CHILD_ID);
        return ChildDetailsFragment.newInstance(childId);
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        Log.i(TAG, "onCreate() called");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.i(TAG, "onStart() called");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume() called");

    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "onPause() called");
    }

    @Override
    protected void onStop() {
        super.onStop();
        String  uuid = getIntent().getSerializableExtra(EXTRA_CHILD_ID).toString();
        Log.i(TAG, "onStop() called" + uuid);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestroy() called");
    }
}

fragment B

public class ChildDetailsFragment extends Fragment{


    private RecyclerView mRecyclerView;
    private Child mChild;

    private static final String ARGS_ID = "child_id";
    private static final String SAVED_INSTANCE_STATE_UUID = "clinicbook.childdetailsfragment.mchildid";



    public static ChildDetailsFragment newInstance(UUID childId) {
        ChildDetailsFragment childDetailsFragment = new ChildDetailsFragment();

        Bundle args = new Bundle();
        args.putSerializable(ARGS_ID, childId);

        childDetailsFragment.setArguments(args);
        return childDetailsFragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("ChildDetailsFragment", "onCreate Called");
        ChildList childList = ChildList.getChildList(getActivity());
        UUID childId = (UUID) getArguments().getSerializable(ARGS_ID);
        mChild = childList.getChild(childId);
    }



    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_child_details, container, false);

        ((AppCompatActivity)getActivity()).getSupportActionBar().setTitle(mChild.getFirstName() + " " + mChild.getLastName());

        mRecyclerView = (RecyclerView) v.findViewById(R.id.child_recycler_view);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        mRecyclerView.setAdapter(new CategoryAdapter());

        return  v;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("ChildDetailsFragment", "onDestroy Called");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.i("ChildDetailsFragment", "fragment onStopCalled");
    }


    ///////////////////////////////////////////////////////////////
    //RecyclerView ViewHolder

    private class CategoryHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        public CategoryHolder(LayoutInflater inflater, ViewGroup parent) {
            super(inflater.inflate(R.layout.category_list_item, parent, false));
            ((LinearLayout) itemView).setOnClickListener(this);
        }

        public void bind(String category) {
            TextView categoryTitle = itemView.findViewById(R.id.category_title);
            categoryTitle.setText(category);
        }

        @Override
        public void onClick(View view) {
            Intent intent = new Intent(getActivity(), PersonalDataActivity.class);
            startActivity(intent);
        }
    }

    //RecyclerView ViewHolder
    ///////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////
    //RecyclerView Adapter

    private class CategoryAdapter extends RecyclerView.Adapter<CategoryHolder> {

        private final String[] mCategoryList = {
                "Personal Data",
                "Growth Measurements",
                "Growth Stages",
                "Immunisations",
                "Medications",
                "Allergies"
        };

        @Override
        public CategoryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            LayoutInflater inflater = LayoutInflater.from(getActivity());
            return new CategoryHolder(inflater, parent);
        }

        @Override
        public void onBindViewHolder(CategoryHolder holder, int position) {
            String category = mCategoryList[position];
            holder.bind(category);
        }

        @Override
        public int getItemCount() {
            return mCategoryList.length;
        }
    }
    //RecyclerView Adapter
    ///////////////////////////////////////////////////////////////

}// End of Class ChildDetailsFragment

Activity C

public class PersonalDataActivity extends SingleFragmentActivity {
    @Override
    protected Fragment createFragment() {
        return new PersonalDataFragment();
    }
}

fragment C 公共(public)类 PersonalDataFragment 扩展 Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_personal_data, container, false);
        return v;
    }
}

AndroidManifest.xml

<activity android:name=".ChildrenActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
<activity android:name=".ChildDetailsActivity"
    android:parentActivityName=".ChildrenActivity">
</activity>
<activity android:name=".PersonalDataActivity"
    android:parentActivityName=".ChildDetailsActivity">
</activity>

堆栈跟踪 fatal error 如下:

12-02 22:42:18.330 16037-16037/com.navsaria.keeran.clinicbook E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                Process: com.navsaria.keeran.clinicbook, PID: 16037
                                                                                java.lang.RuntimeException: Unable to start activity ComponentInfo{com.navsaria.keeran.clinicbook/com.navsaria.keeran.clinicbook.ChildDetailsActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.util.UUID.toString()' on a null object reference
                                                                                    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2479)
                                                                                    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2539)
                                                                                    at android.app.ActivityThread.access$900(ActivityThread.java:168)
                                                                                    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1378)
                                                                                    at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                    at android.os.Looper.loop(Looper.java:150)
                                                                                    at android.app.ActivityThread.main(ActivityThread.java:5659)
                                                                                    at java.lang.reflect.Method.invoke(Native Method)
                                                                                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:822)
                                                                                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:712)
                                                                                 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.util.UUID.toString()' on a null object reference
                                                                                    at com.navsaria.keeran.clinicbook.ChildList.getChild(ChildList.java:67)
                                                                                    at com.navsaria.keeran.clinicbook.ChildDetailsFragment.onCreate(ChildDetailsFragment.java:50)
                                                                                    at android.support.v4.app.Fragment.performCreate(Fragment.java:2339)
                                                                                    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1377)
                                                                                    at android.support.v4.app.FragmentTransition.addToFirstInLastOut(FragmentTransition.java:1109)
                                                                                    at android.support.v4.app.FragmentTransition.calculateFragments(FragmentTransition.java:996)
                                                                                    at android.support.v4.app.FragmentTransition.startTransitions(FragmentTransition.java:99)
                                                                                    at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2364)
                                                                                    at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2322)
                                                                                    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2229)
                                                                                    at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3221)
                                                                                    at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3171)
                                                                                    at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:192)
                                                                                    at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:560)
                                                                                    at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:177)
                                                                                    at com.navsaria.keeran.clinicbook.ChildDetailsActivity.onStart(ChildDetailsActivity.java:56)
                                                                                    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1241)
                                                                                    at android.app.Activity.performStart(Activity.java:6392)
                                                                                    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2442)
                                                                                    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2539) 
                                                                                    at android.app.ActivityThread.access$900(ActivityThread.java:168) 
                                                                                    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1378) 
                                                                                    at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                                    at android.os.Looper.loop(Looper.java:150) 
                                                                                    at android.app.ActivityThread.main(ActivityThread.java:5659) 
                                                                                    at java.lang.reflect.Method.invoke(Native Method) 
                                                                                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:822) 
                                                                                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:712) 

测试设备为华为P9 lite

最佳答案

找到解决方案:

将 AndroidManifest 中 ChildDetailsActivity 的 launchMode 更改为“singleTop”,以便返回堆栈中的 Activity 接收 Intent,而不是创建新 Activity。

<activity android:name=".ChildDetailsActivity"
    android:parentActivityName=".ChildrenActivity"
    android:launchMode="singleTop">
</activity>

关于java - 使用工具栏向上箭头导航会重新启动应用程序,但 Android 内置箭头按钮可以工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47572907/

相关文章:

java - 如何在 Android 上的 fragment 中使用共享首选项?

android - 改编自 Firestore 的 Recyclerview 未出现在 Fragment 上(带标签)

java - DefaultTableModel setDataVector 将旧行附加到新行

java - 更新文本文件定界符java

java - 具有 READ COMMITTED 隔离级别的 SQL 并发 'select then update' 模式

java - 解码时未找到类 : Parcelable (Android)

java - 在 fragment 中设置布局管理器时,在 Recyclerview 上出现空指针异常

java - 循环 "If Else Statement"java

android - 如何在不更新 APK 文件的情况下解决违反使用 Android 广告 ID 政策和第 4.8 节的问题

android - 在android中使用jfoenix