【问题标题】:Yet again findFragmentByTag() returns null再次 findFragmentByTag() 返回 null
【发布时间】:2017-05-05 12:16:38
【问题描述】:

我已经阅读了无数关于 findFragmentByTag() 返回 null 问题的 SO 文章,但几天后,我仍然无法让它工作。所以我听说可以在上面发布我自己的问题。

我有一个容器和三个片段。我希望能够从 A-->B-->C-->A--> 等或向后滑动/甩动。也就是说,向左滑动或向右滑动可循环浏览片段面板。
我有所有这些工作。但我的问题是,一旦我从 A 滑回 A 的整个周期,我与 TextView 字段的所有连接都不再起作用(这些片段中有许多实时更新的文本字段)。那就是更新不再存在,我再也看不到字段的更改;我可以 setText("foo") 到一个字段,但新值不再显示。当片段出现时,它不再有任何文本视图更新。就好像片段的原始实例在某处丢失了,而显示的实例是一个新实例。 根据 logcat 结果,我认为这正在发生。事实上,findFragmentByTag总是返回 null,因此代码每次滑动都会创建新的片段。

我想保留每个实例(A、B 和 C),以便它们保持状态,并且在我浏览片段时可以看到对它们的持续更新。 这是完整的代码文件:

package com.company.myApp;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

public class Fragment_ProgressBar extends Fragment {
    final static String TAG = "Fragment_ProgressBar";
    final static String FRAGMENT_TAG_SUMMARY     = "Fragment_Summary";
    final static String FRAGMENT_TAG_PROGRESSBAR = "Fragment_ProgressBar";
    final static String FRAGMENT_TAG_TIME  = "Fragment_Time";
    final static String DIRECTION_LEFT  = "DIRECTION_LEFT";
    final static String DIRECTION_RIGHT = "DIRECTION_RIGHT";
    public final static String CURRENT_FRAGMENT = FRAGMENT_TAG_PROGRESSBAR;
    final Fragment thisFragment = this;

    public Fragment_ProgressBar(){}

    @Override
    public View onCreateView(LayoutInflater inflater,
                             ViewGroup container,
                             Bundle savedInstanceState) {

        final GestureDetector gesture = new GestureDetector(getActivity(),
                new GestureDetector.SimpleOnGestureListener() {

                    @Override
                    public boolean onDown(MotionEvent e) {
                        return true;
                    }

                    @Override
                    public boolean onFling(MotionEvent event1,
                                           MotionEvent event2,
                                           float velocityX,
                                           float velocityY) {
                        final int SWIPE_MIN_DISTANCE = 120;
                        final int SWIPE_MAX_OFF_PATH = 250;
                        final int SWIPE_THRESHOLD_VELOCITY = 200;
                        try {
                            if (Math.abs(event1.getY() - event2.getY()) > SWIPE_MAX_OFF_PATH)
                                return false;
                            if (event1.getX() - event2.getX() > SWIPE_MIN_DISTANCE
                                    && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                                Log.i(TAG, "Right to Left");
                                showFragment_RightToLeft(FRAGMENT_TAG_TIMECIRCLE);
                            } else if (event2.getX() - event1.getX() > SWIPE_MIN_DISTANCE
                                    && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                                Log.i(TAG, "Left to Right");
                                showFragment_LeftToRight(FRAGMENT_TAG_SUMMARY);
                            }
                        } catch (Exception e) {
                            // nothing
                        }
                        return super.onFling(event1, event2, velocityX, velocityY);
                    }
                });

        View view = inflater.inflate(R.layout.fragment_progress_bar, container, false);
        view.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return gesture.onTouchEvent(event);
            }
        });
        // Inflate the layout for this fragment
        return view;
    }

    private Fragment getNewFragment(String name){
        Log.i(TAG,String.format("Fragment (%s) not found; creating new instance.", name));
        switch (name) {
            case FRAGMENT_TAG_SUMMARY:
                return new Fragment_Summary();
            case FRAGMENT_TAG_PROGRESSBAR:
                return new Fragment_ProgressBar();
            case FRAGMENT_TAG_TIME:
                return new Fragment_Time();
        }
        return null;
    }

    private void showFragment_LeftToRight(String nextFragmentNameTag)
    {

        Fragment nextFragment = getChildFragmentManager().findFragmentByTag(nextFragmentNameTag);
        if (nextFragment == null)
            nextFragment = getNewFragment(nextFragmentNameTag);
        if (nextFragment == null)
            return;

        FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.setCustomAnimations(R.animator.slide_in_left, R.animator.slide_out_right);
        ft.remove(thisFragment);
        ft.add(R.id.overview_fragment_container, nextFragment, nextFragmentNameTag);
        ft.addToBackStack(null);
        ft.commit();
        getFragmentManager().executePendingTransactions();

    }
    private void showFragment_RightToLeft(String nextFragmentNameTag)
    {
        Fragment nextFragment = getChildFragmentManager().findFragmentByTag(nextFragmentNameTag);
        if (nextFragment == null)
            nextFragment = getNewFragment(nextFragmentNameTag);
        if (nextFragment == null)
            return;

        FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.setCustomAnimations(R.animator.slide_in_right, R.animator.slide_out_left);
        ft.replace(R.id.overview_fragment_container, nextFragment, nextFragmentNameTag);
        ft.addToBackStack(null);
        ft.commit();
        getFragmentManager().executePendingTransactions();

    }

}

【问题讨论】:

  • 我尝试将 findFragmentByTag() 调用放在主要活动中,但没有任何区别。仍然为空。
  • 你为什么要在私有片段管理器 getChildFragmentManager() 中寻找片段,却在主片段管理器 getFragmentManager() 中处理它?其次,当您调用删除和替换时,您如何期望片段仍然存在??
  • 无知!答案很简单!我刚刚更改为 getChildManager,它现在可以工作了。谢谢!
  • 如果你想把你的答案放在答案块中,我很乐意为你服务。

标签: android android-fragments


【解决方案1】:

首先,您正在寻找片段,就好像它们作为子片段附加到Fragment_ProgressBar一样,您的所有片段仍由活动片段管理器管理,因此您在错误的位置寻找片段。

其次,每次在执行事务时调用FragmentTransaction.remove()FragmentTransaction.replace(),您都会从片段管理器中删除旧片段。

我还建议您添加/重新附加新片段并分离旧片段(片段已从 UI 中删除,但其状态仍由片段管理器主动管理)。

【讨论】:

  • 如果我想添加一个新片段存储旧片段,正确的顺序是什么?在我add新片段之前,我不需要removereplace 旧片段吗?
  • 如果您调用remove 或使用replace,那么片段管理器将不会存储旧的片段管理器(除非您想保留片段实例,这可能不会给您带来流畅的流程)。只需分离旧的,然后添加(新)/重新附加(预先存在的)一个。
猜你喜欢
  • 1970-01-01
  • 2017-12-22
  • 2018-07-14
  • 1970-01-01
  • 2014-03-04
  • 1970-01-01
  • 2016-04-03
  • 1970-01-01
相关资源
最近更新 更多