[Из песочницы] Как я с лагом Navigation Drawer боролся

Привет, Хабр!Меня зовут Алексей. Я разрабатываю под Android. Отладка в эмуляторе подобна смерти, поэтому я пользуюсь своим HTC Desire HD. Зверёк уже очень древний, за что я не могу его не любить, потому что любые шероховатости и неровности в приложении на нём отдаются славными лагами. Кстати, очень рекомендую запускать свои проекты на аппаратах средней мощности, ведь не у всех пользователей флагманы. Так вот, работая над своим новым приложением, я обнаружил, что при переключении между фрагментами через Navigation Drawer шторка навигации заметно пролагивает. При создании фрагмента делались запросы к базе и подгружались SharedPreferences. Мне было просто противно наблюдать этот лаг, и я придумал как избавиться от него. Всех, кому интересно, прошу под кат.Я создал простенький проект с NavigationDrawer и тремя фрагментами (ссылка на Github в конце статьи). Код не претендует на звание идеального, я старался написать максимально просто и понятно. Код шторки взят прямо из примеров Google. Решил проблему я очень просто и в лоб: загрузка фрагмента запускается в отдельном потоке и задерживается на 0,3 секунды (магическое число, подобранное экспериментально).

Сначала вешаем слушателя на элементы списка так:

mDrawerList.setOnItemClickListener(new DrawerItemClickListener()); И метод selectItem был таким:

private void selectItem(int position) { Fragment fragment = new ContentFragment(); Bundle args = new Bundle(); args.putInt("positions", position); fragment.setArguments(args);

FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();

mDrawerList.setItemChecked(position, true); setTitle(leftDrawerTitles[position]); mDrawerLayout.closeDrawer(mDrawerList); } А чтобы убрать лаг, изменим эти два места:

1) Из selectItem перенесём в onCreate весь код по выделению активного элемента и закрытию Drawer. selectItem станет таким:

private void selectItem(int position) { Fragment fragment = new ContentFragment(); Bundle args = new Bundle(); args.putInt("positions", position); fragment.setArguments(args);

FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit(); } 2) А в onCreate вешаем слушателя на элементы Drawer и запускаем поток:

mDrawerList.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> adapterView, View view, final int position, long l) { mDrawerList.setItemChecked(position, true); setTitle(leftDrawerTitles[position]); mDrawerLayout.closeDrawer(mDrawerList);

// Смена фрагмента запускается в отдельном потоке и задерживается на 0.3 секунды, // чтобы избежать пролагивания при переключении new Thread(new Runnable() { public void run() { try { TimeUnit.MILLISECONDS.sleep(300); selectItem(position); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } }); Вот и всё. Может быть это и нелепый костыль, но я всё равно был безумно рад, открыв его для себя.

P.S. Хотелось бы добавить про отладку на телефоне. Очень рекомендую пользоваться ADB Over Wi-Fi (требуются root права). Wi-Fi не ограничивает вас в передвижениях и в поворотах аппарата.P.P.S. Очень хочу получить консруктивную критику и советы знающих людей.

Ссылка на репозиторий: https://github.com/Rozag/Lags-free-navigation-drawer

© Habrahabr.ru