I Предполагается, что вы имеете в виду OFFSCREEN_PAGE_LIMIT_DEFAULT
, а не offsetlimit
, поскольку вы говорите о проблеме предварительной загрузки фрагментов.
И значение по умолчанию -1
не ноль https://developer.android.com/reference/androidx/viewpager2/widget/ViewPager2.html#OFFSCREEN_PAGE_LIMIT_DEFAULT
и значение по умолчанию означает
Значение, указывающее, что механизм кэширования по умолчанию RecyclerView должен использоваться вместо явной предварительной выборки и сохранения страниц по обе стороны от текущей страницы.
Поскольку это оптимизация производительности просмотра переработчика, я бы сказал, что это не является гарантией того, что он не будет предварительно загружать ваши фрагменты, он просто остается за механизмом кэширования обзора переработчика.
Существует ряд факторов, которые могут повлиять на механизм кэширования в просмотрнике.
Если предзагрузка вашего фрагмента является проблемой, потому что у вас есть динамические c данные, которые вы хотите загружать только когда страница показано, что было бы лучше переместить ваш фрагмент, чтобы использовать метод «отложенной загрузки», т.е. загружать данные только тогда, когда они отображаются.
У меня был Аналогичная проблема с оригинальным viewpager и решена с помощью «ленивой загрузки». Если проблема заключается в том, что время загрузки ваших динамических c данных является проблемой, обновите вопрос, и тогда я смогу наметить возможное решение.
Обновление: 3
It Кажется, что Viewpager2 на самом деле корректно работает с жизненным циклом фрагментов, в отличие от исходного Viewpager, поэтому вы можете вызвать updateView()
, как показано в примере update2, из метода Fragments onResume
без необходимости использовать обратный вызов pageSelected
через адаптер для запуска обновления the View.
Обновление:
Я считаю, что фактическая причина просмотра кода viewpager2 заключается в том, что при выборе вкладки выполняется фальшивое перетаскивание с плавной прокруткой и плавной прокруткой выбранный элемент +1 к кешу, если вы проведете пальцем от Tab0 к Tab1 самостоятельно, это не создаст Tab2
ViewPager2 немного отличается, и метод "отложенной загрузки", который я использовал для оригинального ViewPager, не совсем подходит, но есть немного другой способ сделать то же самое.
Основная идея с оригинальным ViewPager была обновлять представление ТОЛЬКО в том случае, если страница была выбрана с помощью onPageChangeListener, но ViewPager2 вместо нее использует обратный вызов
Поэтому добавьте следующее после создания ViewPager2 (обычно в Activity onCreate)
viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
// Tell the recyclerview that position 2 has changed when selected
// Thus it recreates it updating the dynamic data
if (position == 2) {
// the adapter for the ViewPager needs to a member of the Activity class so accessible here
adapter.notifyItemChanged(position);
}
}
});
Это проще, но имеет незначительный недостаток, заключающийся в том, что данные Dynami c загружаются при предварительной загрузке, а затем снова при фактическом отображении.
Update2: Более эффективное добавление к Первый метод больше похож на мой оригинальный подход
Это полный рабочий пример, поскольку его легче объяснить.
Основная идея заключается в вашем фрагменте с динамическими данными c, которые вы ТОЛЬКО используете загрузка при отображении означает создание пустого элемента представления «заполнитель», и вы не заполняете его данными во фрагментах onViewCreated
, в данном примере это второй textview
без текста, но он может быть Вторичное представление с нулевыми объектами или любым другим типом представления.
В своем фрагменте вы затем создаете метод для обновления "заполнителя" с данными (в этом случае метод называется updateView()
, который устанавливает текстовый вид текста на текущую дату и время)
Затем в вашем адаптере фрагментов вы сохраняете ссылку на каждый фрагмент, который он создает, в ArrayList
(это позволяет получить фрагмент обратно), а затем вы создаете метод updateFragment()
в адаптере, который использует позицию, чтобы получить возможность фрагмента вызвать updateView()
для него.
Наконец, снова вы используете onPageSelected
для вызова updateFragment
с позиции, которую вы хотите динамически обновить.
Таким образом, textview1
показывает данные и время создания фракции, а textview2
отображается только на третьей вкладке. и имеет дату и время, когда страница была выбрана. Обратите внимание, что texview1
на «Tab 2» и «Tab 3» - это то же самое время, когда вы нажимаете на «Tab 2» заголовки для изменения вкладок (это проблема в вопросе)
MainActivity. java
package com.test.viewpager2;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import android.os.Bundle;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
public class MainActivity extends AppCompatActivity {
TabLayout tabLayout;
ViewPager2 viewPager2;
ViewPager2Adapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager2 = findViewById(R.id.viewpager2);
tabLayout = findViewById(R.id.tabLayout);
viewPager2.setAdapter(createCardAdapter());
new TabLayoutMediator(tabLayout, viewPager2,
new TabLayoutMediator.TabConfigurationStrategy() {
@Override public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
tab.setText("Tab " + (position + 1));
}
}).attach();
viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
// Tell the recyclerview that position 2 has changed when selected
// Thus it recreates it updating the dynamic data
if (position == 2) {
adapter.updateFragment(position);
}
}
});
}
private ViewPager2Adapter createCardAdapter() {
adapter = new ViewPager2Adapter(this);
return adapter;
}
}
ViewPager2Adapter. java
package com.test.viewpager2;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import java.util.ArrayList;
public class ViewPager2Adapter extends FragmentStateAdapter {
private static final int numOfTabs = 3;
private ArrayList<Fragment> fragments = new ArrayList<>();
public ViewPager2Adapter(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
}
@NonNull @Override public Fragment createFragment(int position){
Fragment fragment = TextFragment.newInstance(position);
fragments.add(fragment);
return fragment;
}
@Override
public int getItemCount(){
return numOfTabs;
}
public void updateFragment(int position){
Fragment fragment = fragments.get(position);
// Check fragment type to make sure it is one we know has an updateView Method
if (fragment instanceof TextFragment){
TextFragment textFragment = (TextFragment) fragment;
textFragment.updateView();
}
}
}
TextFragment. java
package com.test.viewpager2;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
public class TextFragment extends Fragment {
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private int mParam1;
private View view;
public TextFragment() {
// Required empty public constructor
}
public static TextFragment newInstance(int param1) {
TextFragment fragment = new TextFragment();
Bundle args = new Bundle();
args.putInt(ARG_PARAM1, param1);
fragment.setArguments(args);
Log.d("Frag", "newInstance");
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getInt(ARG_PARAM1);
}
Log.d("Frag", "onCreate");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
Log.d("Frag", "onCreateView");
view = inflater.inflate(R.layout.fragment_text, container, false);
return view;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
Bundle args = getArguments();
TextView textView1 = view.findViewById(R.id.textview1);
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH-mm-ss.sss", Locale.US);
String dt = df.format(Calendar.getInstance().getTime());
textView1.setText(dt);
}
public void updateView(){
Log.d("Frag", "updateView");
TextView textView2 = view.findViewById(R.id.textview2);
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH-mm-ss.sss", Locale.US);
String dt = df.format(Calendar.getInstance().getTime());
textView2.setText(dt);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
Log.d("Frag", "onAttach");
}
@Override
public void onDetach() {
super.onDetach();
Log.d("Frag", "onDetach");
}
}
activity_main. xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager2"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tabLayout" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".TextFragment">
<TextView
android:id="@+id/textview1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textview2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textview1" />/>
</androidx.constraintlayout.widget.ConstraintLayout>