How I struggled with the Navigation Drawer lag

Hello, Habr!

My name is Aleksey. I am developing for Android. Debugging in the emulator is like death, so I use my HTC Desire HD. The animal is already very ancient, for which I can not help but love it, because any roughness and irregularities in the application on it are given by glorious lags. By the way, I highly recommend launching your projects on medium-power devices, because not all users have flagships. So, while working on my new application, I found that when switching between fragments through the Navigation Drawer, the navigation curtain draws noticeably. When creating a fragment, queries to the database were made and SharedPreferences were loaded. I was just disgusted to watch this lag, and I figured out how to get rid of it. Anyone who is interested, I ask under the cat.

I created a simple project with NavigationDrawer and three snippets (link to Github at the end of the article). The code does not claim to be perfect, I tried to write as simple and clear as possible. The curtain code is taken directly from Google examples . I solved the problem very simply and forehead: loading a fragment is launched in a separate stream and is delayed by 0.3 seconds (a magic number, selected experimentally).

First, we hang the listener on the list items like this:

mDrawerList.setOnItemClickListener(new DrawerItemClickListener());


And the selectItem method was like this:

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);
}


And in order to remove the lag, we change these two places:

1) From selectItem, we transfer all the code to select the active element and close the Drawer to onCreate. selectItem will become like this:

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) And in onCreate we hang the listener on Drawer elements and start the stream:

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();
	}
});


That's all. It may be an absurd crutch, but I was still extremely happy to discover it for myself.

PS I would like to add about debugging on the phone. I highly recommend using ADB Over Wi-Fi (root privileges are required). Wi-Fi does not limit you in the movements and in the turns of the device.
PPS I really want to get constructive criticism and advice from knowledgeable people.

Link to repository: https://github.com/Rozag/Lags-free-navigation-drawer

Also popular now: