addTab () не добавляет никаких TabLayout.Tab при обратном вызове - PullRequest
0 голосов
/ 02 ноября 2019

При добавлении вкладок в OnCreate проблем нет, вкладки добавляются нормально, но при добавлении вкладок в вызове onChange пакета LiveDataObserver ничего не происходит.

У меня есть ViewPager с 2 фрагментами внутри2-й фрагмент У меня есть второй Viewpgaer с еще 2 Fragemnts, этот второй виртуальный вице-президент имеет com.google.android.material.tabs.TabLayout, но TabLayout НЕ связан через .setupWithViewPager ().

EDIT: Конфигурация будет выглядеть примерно так:

MainActivity (Nav) -> MainFrag (ViewPager) -> ChildFrag (в 1-й позиции) ... <- это TabLayout </p>

Продолжить :

Этот TabLayout показывает только содержимое второго самого внутреннего viewPager, это означает, что он должен отображать только 2 вкладки, не более того.

Но яЯ хочу добавить эти две вкладки с помощью обратных вызовов LiveData.

Я особенно не хочу, чтобы они (viewpager и tablayout) были связаны, потому что я хочу, чтобы фрагменты были созданы один раз, но ятакже хочу, чтобы вкладки выглядели так, как если бы пользователь создавал их на лету.

Если я создаю Fragemtns, с единственной целью добавления вкладок, я рискую получать информацию из БД каждый раз, когда это происходит. Готово, даже если пользователь выбирает одну и ту же опцию дважды.

Кроме того, если фрагменты уже созданы, разбиение на страницы становится плавным. Любой ценой я избегаю использования notifyDataSetChanged (), потому что мне не нравится, как данные перемещаются с этой опцией, это главная причина.

Так что я хочу .addTab () в onChange LiveData, поэтомучто я могу создавать вкладки с заголовками, которые предоставляет LiveData.

Пока ничего не происходит

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        app:tabSelectedTextColor="@android:color/white"


        app:layout_constraintBottom_toTopOf="@id/guideline"
        app:layout_constraintTop_toTopOf="parent"
        app:tabTextColor="@android:color/black"
        >

То есть XML

public class FlyHighSubFragment extends Fragment {




    private WeakReference<FlyHighActivity> mContextWeakReference;
    private MySubFragmentPagerAdapter mAdapter;
    private FragmentFlyhighSubBinding binding;


    private TabLayout mTabLayout;

    private SharedViewModel mSharedViewModel;



    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        if (context instanceof FlyHighActivity) {

            mContextWeakReference = new WeakReference<>((FlyHighActivity)context);

        }
    }

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



        binding = DataBindingUtil.inflate(inflater,
                R.layout.fragment_flyhigh_sub, container, false);


        mAdapter = new MySubFragmentPagerAdapter(getChildFragmentManager());

        binding.mainContainer.setAdapter(mAdapter);



        mTabLayout = binding.tablayout;

        mTabLayout.addOnTabSelectedListener(new TabLayout.BaseOnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                binding.mainContainer.setCurrentItem(tab.getPosition());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });

        binding.mainContainer.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout));
}

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mSharedViewModel = ViewModelProviders.of(mContextWeakReference.get()).get(SharedViewModel.class);
/*called on the process of going from page [0][0] to page [1][0]*/
        mSharedViewModel.getUserName().observe(getViewLifecycleOwner(), new Observer<String>() {
            @Override
            public void onChanged(String s) {

                mTabLayout.addTab(mTabLayout.newTab().setText(s));




            }
        });
/*called on the process of going from [1][0] to [1][1]*/
        mSharedViewModel.getSessionTitle().observe(getViewLifecycleOwner(), new Observer<String>() {
            @Override
            public void onChanged(String s) {
            mTabLayout.addTab(mTabLayout.newTab().setText(s));
            }
        });

    }

}

РЕДАКТИРОВАТЬ:

Моя SharedViewModel:

public class SharedViewModel extends ViewModel {

    private static final String TAG = "SharedViewModel";

/*Each one of this Strings are passed from Fragment to Fragment, some of them trigger a Firebase listener, others provide view data for the Fragment.*/

/*All of them do their job properly, even the ones called inside the FlyHighSubFragment which is the Fragment that shelters the TabLayout*/

    private MutableLiveData<String> uId = new MutableLiveData<>();
    private MutableLiveData<String> userName = new MutableLiveData<>();
    private MutableLiveData<String> chatRef = new MutableLiveData<>();
    private MutableLiveData<String> sessionTitle = new MutableLiveData<>();
    private MutableLiveData<Sessions> session = new MutableLiveData<>();

    public SharedViewModel() {

    }

    public MutableLiveData<Sessions> getSession() {
        return session;
    }

    public void setSession(Sessions session) {
        this.session.setValue(session);
    }

    public MutableLiveData<String> getSessionTitle() {
        return sessionTitle;
    }

    public void setSessionTitle(String sessionTitle) {
        this.sessionTitle.setValue(sessionTitle);
    }

    public MutableLiveData<String> getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName.setValue(userName);
    }

    public LiveData<String> getUid() {
        return uId;
    }

    public void setUid(String input) {
        uId.setValue(input);
    }

    public MutableLiveData<String> getChatRef() {
        return chatRef;
    }

    public void setChatRef(String chatRef) {
        this.chatRef.setValue(chatRef);
    }

}

Это мой SubFragmentPagerAdapter, который является адаптером для самого внутреннего ViewPager (тот, который использует getChildFragmentManager ())

Важно отметить, что это viewPager НИЖЕ TabLayout, НО Фрагмент TabLayout имеет родителя, который является другим ViewPager и имеет идентичную конфигурацию .... FragmentPagerAdapter, "BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT" и Фрагменты, инициализированные в конструкторе, вы можетевижу, что notifyDatasetChanged () нет, потому что я управляю всей информацией с помощью обратных вызовов LiveData:

public class MySubFragmentPagerAdapter extends FragmentPagerAdapter {

    private ChatFragment mChatFragment;
    private SessionsFragment mSessionsFragment;

    public MySubFragmentPagerAdapter(@NonNull FragmentManager fm,
                                     FlyHighUser flyHighUser,
                                     MyPagerController.FragmentPager fragmentPagerController) {
        super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);

        mChatFragment = ChatFragment.newInstance(flyHighUser);
        mSessionsFragment = new SessionsFragment();

/*This is a listener I made that allows the Fragments to be able to change the pages of their parent viewPgaer.*/
        mSessionsFragment.setSessionFragmentInterface(fragmentPagerController);


    }


    private static final int NUMBER_OF_FRAGMENTS = 2;

    @NonNull
    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return mSessionsFragment;
            case 1:
                return  mChatFragment;
        }
        return null;
    }


    @Override
    public int getCount() {
        return NUMBER_OF_FRAGMENTS;
    }




}

полный процесс должен выглядеть следующим образом:

MainActivity (Nav) / MainFrag (viewPager) / Frag (в 0)

@Override
public void onItemClick(String uID, String userName) {


/*Set the values that Fragment at position 1 should solve, this include connecting the FireBase Listener with the uid, and getting the userName String*/
        mSharedViewModel.setUid(uID);
        mSharedViewModel.setUserName(userName);

/* this changes the page to position 1*/

    fragmentPagerController.scrollToFragment(1);
}

Когда страница меняется на 1, две вещи должны происходить одновременно,Необходимо добавить вкладку, и SessionsFragment (созданный при инициализации) должен добавить прослушиватель Firebase к указанной ссылке

MainActivity (Nav) / MainFrag (viewPager) / Frag (в 1) (subViewPgaer + TabLayout).

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mSharedViewModel = ViewModelProviders.of(mContextWeakReference.get()).get(SharedViewModel.class);
        mSharedViewModel.getUserName().observe(getViewLifecycleOwner(), new Observer<String>() {
            @Override
            public void onChanged(String s) {
/*The Tab is added but not drawn*/
                mTabLayout.addTab(mTabLayout.newTab().setText(s));




            }
        });
        mSharedViewModel.getSessionTitle().observe(getViewLifecycleOwner(), new Observer<String>() {
            @Override
            public void onChanged(String s) {
/* The Tab is added but not drawn*/
            mTabLayout.addTab(mTabLayout.newTab().setText(s));
            }
        });
}

MainActivity (Nav) / MainFrag (viewPager) / Frag (в 1) (subViewPgaer + TabLayout) / Frag (в 0) <- AKA: SessionsFragment </p>

            @Override
            public void onActivityCreated(@Nullable Bundle savedInstanceState) {
                super.onActivityCreated(savedInstanceState);
                mSharedViewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
                mSharedViewModel.getUid().observe(getViewLifecycleOwner(), new Observer<String>() {
                    @Override
                    public void onChanged(String s) {

                        uid = s;
        /*this works perfectly fine, I wanted the Firebase data to be bound by the MainActivity LifeCycle.
Observer is added only once, and there is only one Firebase Listener at any given moment (italian chef kiss) BTW observeUserSessions() is a LiveData setter for the observer, lifeCycleOwner and Firebase reference*/
                        mContextWeakReference.get().observeUserSessions(mObserver, "sessions/" + s);


                    }
                });
                mSharedViewModel.getUserName().observe(getViewLifecycleOwner(), new Observer<String>() {
                    @Override
                    public void onChanged(String s) {
                        clientName = s;
    /*this is viewDataBinding*/
                        binding.setClientName(clientName);

                    }
                });
            }

Сообщения об ошибках отсутствуют, вкладки добавляются, но не отображаются.

1 Ответ

0 голосов
/ 04 ноября 2019

Это не совсем ответ, но я полагаю, что причина, по которой это происходит, та же самая причина, по которой мы должны использовать getChildFragmentManager () при использовании ViewPager внутри другого Viewpager.

Возможно, потому чтожизненный цикл настолько слоистый что у вкладок вне процесса инициализации нет никаких шансов, может быть, контейнеры с фрагментами не могут найти что-то, к чему можно присоединиться, это может быть инфлятор ?, контейнер? Я действительно ничего не знаю об архитектуре Android, если бы у меня не было таких проблем.

Дело в том, что Tablayout.Tab не имеет возможности получить правильное представление, необходимое от своего родителя, или, возможно, проблемаполагается непосредственно на сам TabLayout без возможности монтировать правильный FragmentManager. или, может быть, он есть, но я не нашел его, я думаю, что это главная проблема.

В любом случае, я бы полностью понял, если эти вопросы намеренно остаются проблемными, после того как я признаю некоторые из предоставленных инструментоввиджеты и компоненты android.os действительно достаточны для создания чего-либо с полной настройкой, если знание об их использовании будет масштабироваться, а их поведение будет оставаться неизменным без учета обстоятельств, проблема в том, чтоза занавесом происходит так много вещей, что знать как их использовать, означает только знать, как использовать их так, как они предназначались, что в действительности означает, что человек вообще ничего не знает. ... и я лично считаю, что было бы несправедливо по отношению к людям, которые потратили годы на освоение системы, если бы кто-то с поверхностным пониманием компонентов и виджетов архитектуры андроида мог построить что-то по номиналу.

...