У меня TabLayout настроен с помощью viewpager. Viewpager настроен с адаптером. К адаптеру добавлено 11 фрагментов, и каждый фрагмент имеет обзор переработчика. Когда я запускаю приложение, пролистывание между фрагментами идет медленно. Может кто-нибудь сказать мне причину этой проблемы?
Моя MainActivity:
myTabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
mainViewPager = (ViewPager) findViewById(R.id.mainViewPager);
tabLayoutAdapter = new TabLayoutAdapter(getSupportFragmentManager());
tabLayoutAdapter.addFragment(new HomeFragment());
tabLayoutAdapter.addFragment(new ClipFragment());
tabLayoutAdapter.addFragment(new MovieFragment());
tabLayoutAdapter.addFragment(new SerialFragment());
tabLayoutAdapter.addFragment(new MusicFragment());
tabLayoutAdapter.addFragment(new BookFragment());
tabLayoutAdapter.addFragment(new PixFragment());
tabLayoutAdapter.addFragment(new GameFragment());
tabLayoutAdapter.addFragment(new NewsFragment());
tabLayoutAdapter.addFragment(new LiveFragment());
tabLayoutAdapter.addFragment(new AdvancedSearchFragment());
mainViewPager.setAdapter(tabLayoutAdapter);
myTabLayout.setupWithViewPager(mainViewPager);
Мой адаптер:
public class TabLayoutAdapter extends FragmentStatePagerAdapter {
List<Fragment> tabPages = new ArrayList<>();
public TabLayoutAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return tabPages.get(position);
}
@Override
public int getCount() {
return tabPages.size();
}
public void addFragment(Fragment page){
tabPages.add(page);
}
}
Фрагмент образца:
public class MovieFragment extends Fragment {
RecyclerView movieRecyclerView;
List<Movie> movieList;
MovieAdapter movieAdapter;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("Fragment", "thread = " + Thread.currentThread().getName());
Log.i("Fragment", "thread = " + Thread.currentThread().getName());
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View movieView = inflater.inflate(R.layout.tab_movie, container, false);
return movieView;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
movieRecyclerView = (RecyclerView) view.findViewById(R.id.movieRecyclerView);
movieList = new ArrayList<Movie>();
movieAdapter = new MovieAdapter(view.getContext(), movieList);
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(view.getContext(), 2);
movieRecyclerView.setLayoutManager(mLayoutManager);
movieRecyclerView.addItemDecoration(new GridSpacingItemDecoration(2, dpToPx(10), false));
movieRecyclerView.setItemAnimator(new DefaultItemAnimator());
movieRecyclerView.setAdapter(movieAdapter);
prepareMovies();
}
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {
private int spanCount;
private int spacing;
private boolean includeEdge;
public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
this.spanCount = spanCount;
this.spacing = spacing;
this.includeEdge = includeEdge;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view); // item position
int column = position % spanCount; // item column
if (includeEdge) {
outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)
if (position < spanCount) { // top edge
outRect.top = spacing;
}
outRect.bottom = spacing; // item bottom
} else {
outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing)
if (position >= spanCount) {
outRect.top = spacing; // item top
}
}
}
}
private void prepareMovies() {
int[] covers = new int[]{
R.drawable.bossbaby,
R.drawable.abeautifulmind,
R.drawable.despicableme,
R.drawable.harrypotter,
R.drawable.thegodfather,
R.drawable.piratesofcaribbean,
};
Movie movie = new Movie("Boss Baby",10000,4.5,20000,16000, covers[0]);
movieList.add(movie);
movie = new Movie("A Beautiful mind",35100,4.9,40000,39000, covers[1]);
movieList.add(movie);
movie = new Movie("Despicable me",20000,4.7,33000,31000, covers[2]);
movieList.add(movie);
movie = new Movie("Harry Potter",90000,5.0,110000,105000, covers[3]);
movieList.add(movie);
movie = new Movie("The God Father",70000,4.9,90000,86700, covers[4]);
movieList.add(movie);
movie = new Movie("Pirates of caribbean",50000,4.6,70000,64000, covers[5]);
movieList.add(movie);
movieAdapter.notifyDataSetChanged();
}
private int dpToPx(int dp) {
Resources r = getResources();
return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics()));
}
}
3 ответа
Если у вас много фрагментов и вы хотите оптимизировать анимацию и взаимодействие, вы можете использовать viewpager.setOffscreenPageLimit(int numberOfPages)
;
setOffscreenPageLimit()
будет иметь значение по умолчанию 1
, т. Е. Viewpager будет загружать только одну страницу (фрагмент) с обеих сторон, а другие страницы будут воссозданы из адаптера при прокрутке и, следовательно, будут отставать в зависимости от операций, которые будет выполнять страница , Таким образом, когда вы знаете количество страниц, тогда использование этого метода поможет в плавности анимации подкачки и взаимодействия.
Из документа setOffscreenPageLimit ()
Установите количество страниц, которые должны быть сохранены по обе стороны от текущей страницы в иерархии представления в состоянии ожидания. Страницы за пределами этот предел будет воссоздан из адаптера при необходимости.
Это предлагается в качестве оптимизации. Если вы заранее знаете количество страниц, которые вам нужно будет поддерживать, или используете на своих страницах механизмы отложенной загрузки, то настройка этого параметра может иметь преимущества в воспринимаемой плавности анимации подкачки и взаимодействия. Если у вас есть небольшое количество страниц (3-4), которые вы можете поддерживать активными все сразу, меньше времени будет потрачено на макет для вновь созданных представлений поддеревьев, поскольку пользовательские страницы перемещаются назад и вперед.
Наряду с ответом @Khemraj, попробуйте следующее также, потому что, когда мы возвращаемся к тому же классу recyclerview
, то есть вероятность проблем с адаптером viewpager
tabLayoutAdapter = new TabLayoutAdapter(getChildFragmentManager());
Вместо того
tabLayoutAdapter = new TabLayoutAdapter(getSupportFragmentManager());
Попробуйте сделать следующее, чтобы сделать навигацию более плавной:
1) в каждом фрагменте перемещайте код из onViewCreated
в onActivityCreated
, потому что это методы вызываются, когда фрагмент появляется полностью:
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// put code of setting data to views etc.
}
2) реализовать следующие методы в классе FragmentStateAdapter
:
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// super.destroyItem(container, position, object);
}
// Force a refresh of the page when a different fragment is displayed
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
3) Используйте несколько изображений с низким разрешением в вашем фрагменте (если вы используете их из папки ресурсов). Не используйте большое разрешение, как - 1024 * 960, попробуйте сжать их, а затем добавить.
4) Избегайте использования wrap_content
в файлах разметки фрагментов. потому что тогда для вычисления высоты ширины требуется время. Если вы можете указать match_parent или любое другое конкретное значение в dp
, оно будет работать намного быстрее.
Попробуйте эти пункты, может быть, они помогут вам.
Новые вопросы
android
Android - это мобильная операционная система Google, используемая для программирования или разработки цифровых устройств (смартфоны, планшеты, автомобили, телевизоры, одежда, стекло, IoT). Для тем, связанных с Android, используйте специальные теги Android, такие как android-intent, android-activity, android-адаптер и т. Д. Для вопросов, не связанных с разработкой или программированием, но связанных с платформой Android, используйте эту ссылку: https: // android.stackexchange.com .