0

I know that there are similar titled questions, but mine is slightly different.....

I have an application that contains one Activity and a number of Fragments. When the application is launched, it checks if the user is logged in. If they are, the home page fragment is launched.For the purposes of this question, I just have a Toast message pop up that says Logged in instead of any fragments being launched. The activity also contains a DrawerLayout, its appropriate override methods, and a number of interface methods from other fragments that tell the main activity what to do.

I'm not retrieving any heavy data or making any URL connections but for some reason I keep getting a "skipped frames/too much work on main thread" warning.

I'm primarily familiar with using ASyncTask when I need to retrieve JSON files, connect to databases and so on. In this case, I'm not sure how to solve my problem. There is a lot of code in the main activity. I'm just not sure what would make the most sense to place in a separate thread and how should I do it? Any suggestions would be much appreciated.

Here is my main Activity:

public class HomePage extends AppCompatActivity implements HomeFragment.OnClickedListener, CalendarFragment.OnClickedCalListener {
private FragmentTransaction ft;
private Fragment fragment;
private DrawerLayout drawerLayout;
private ListView drawerList;
private ActionBarDrawerToggle drawerToggle;
String[] drawerListItems;
private static final String PREFS_LOGGED_IN = "AreYouLoggedInFile";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home_page);

    String appVersion = "v1";
    Backendless.initApp(this, "blah blah", "blah", appVersion);

    if (findViewById(R.id.fragment_container) != null) {
        if (savedInstanceState != null) {

        }else{
            Toast.makeText(getApplicationContext, "Logged In", Toast.LENGTH).show();
        }
    }

    Toolbar myToolbar = (Toolbar) findViewById(R.id.toolBarHome);
    drawerLayout = (DrawerLayout)findViewById(R.id.homePageDrawer);
    drawerList = (ListView)findViewById(R.id.homePageList);
    drawerListItems = getResources().getStringArray(R.array.activities);
    drawerList.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,drawerListItems));
    drawerList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            switch (position) {
                case 0: {
                    fragment = new CalendarFragment();
                    break;
                }
                case 1: {
                    fragment = new ContactsFragments();
                    break;
                }
                case 2: {
                    fragment = new HomeFragment();
                    break;
                }
                case 3:{
                    fragment = new ActivityFragment();
                    break;
                }
                case 4:{
                    Toast.makeText(getApplicationContext(), "Logged Out!", Toast.LENGTH_LONG).show();
                    Intent i = new Intent(HomePage.this, MainLoginActivity.class);
                    SharedPreferences myPrefs = getSharedPreferences(PREFS_LOGGED_IN, 0);
                    SharedPreferences.Editor editor = myPrefs.edit();
                    editor.putBoolean("isLoggedIn", false);
                    editor.commit();
                    startActivity(i);
                    finish();
                    break;
                }
            }
            ft = getFragmentManager().beginTransaction();
            ft.replace(R.id.fragment_container,fragment);
            ft.addToBackStack(null);
            ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
            ft.commit();
            drawerLayout.closeDrawer(drawerList);
        }
    });
    drawerToggle = new ActionBarDrawerToggle(this,drawerLayout,myToolbar,R.string.drawer_open,R.string.drawer_close)
    {
        @Override
        public void onDrawerOpened(View drawerView) {
            super.onDrawerOpened(drawerView);
            invalidateOptionsMenu();
            syncState();
        }

        @Override
        public void onDrawerClosed(View drawerView) {
            super.onDrawerClosed(drawerView);
            invalidateOptionsMenu();
            syncState();
        }
    };
    drawerLayout.setDrawerListener(drawerToggle);
    setSupportActionBar(myToolbar);
    myToolbar.setLogo(R.drawable.happy_dog_icon);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setHomeButtonEnabled(true);
    drawerToggle.syncState();
}


@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    drawerToggle.syncState();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    drawerToggle.onConfigurationChanged(newConfig);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu, menu);
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()){
        case android.R.id.home:{
            if (drawerLayout.isDrawerOpen(drawerList)){
                drawerLayout.closeDrawer(drawerList);
            }else{
                drawerLayout.openDrawer(drawerList);
            }
            return true;
        }case R.id.infoActionBar:{
            Toast.makeText(getApplicationContext(), "Hey", Toast.LENGTH_LONG).show();
        }
        default:return super.onOptionsItemSelected(item);
    }
}

@Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() > 0 ){
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
}

@Override
public void buttonClicked(View v) {
    switch (v.getId()){
        case R.id.logoutButton:{
            Backendless.UserService.logout(new AsyncCallback<Void>() {
                public void handleResponse(Void response) {
                    Toast.makeText(getApplicationContext(), "Logged Out!", Toast.LENGTH_LONG).show();
                    Intent i = new Intent(HomePage.this, MainLoginActivity.class);
                    SharedPreferences myPrefs = getSharedPreferences(PREFS_LOGGED_IN, 0);
                    SharedPreferences.Editor editor = myPrefs.edit();
                    editor.putBoolean("isLoggedIn", false);
                    editor.commit();
                    startActivity(i);
                    finish();
                }

                public void handleFault(BackendlessFault fault) {
                    Toast.makeText(getApplicationContext(), "Did Not Log Out!", Toast.LENGTH_LONG).show();
                }
            });
        }
        case R.id.calendarButton:{
            fragment = new CalendarFragment();
            break;
        }
        case R.id.activityButton:{
            fragment = new ActivityFragment();
            break;
        }
        case R.id.contactsButton:{
            fragment = new ContactsFragments();
            break;
        }
    }
    ft = getFragmentManager().beginTransaction();
    ft.replace(R.id.fragment_container,fragment);
    ft.addToBackStack(null);
    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
    ft.commit();
}

Thank you

Mark F
  • 1,523
  • 3
  • 23
  • 41

2 Answers2

1

OK, without looking at the code i recommend that you run a performance analysis tool on the code. This will show you were the CPU is working the hardest. Most IDEs have this feature, here are some links to popular java/android IDE performance tools (built in, of course):

If your using something different look around for profiling tools for whatever your using.

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
user3797758
  • 829
  • 1
  • 14
  • 28
1

Biggest issue I see with your code is your creating a new fragment every time you change pages. You shouldn't be doing this, you're eating up your memory, especially if all those fragments have a lot of rendering to do. Ideally, you should create fragments once when needed and reuse that fragment when you go back to its drawer icon.

Add LeakCanary to your application, you possible have some memory leaks, likely from the aforementioned issue.

Do you have a large amount of photos in your application? You're probably doing a lot of run time scaling in your application causing Android to GC.

VirtualProdigy
  • 1,637
  • 1
  • 20
  • 40
  • 1
    Hey, I changed my code and am not creating a new Fragment every time a menu option in the DrawerLayout is selected. I'm still getting the warning however. I didn't mention that I am doing this in my emulator. When I attach my device, there are no issues. Is this common with emulators and how much emphasis should I put on mending it? Thanks. – Mark F May 04 '16 at 18:58
  • 1
    Emulators are usually tighter with memory and closer to lower-end devices. How many frames is your device skipping? Take a look at this [post](http://stackoverflow.com/questions/14678593/the-application-may-be-doing-too-much-work-on-its-main-thread), if your skipping around 100, but its fine on a device you should be ok. – VirtualProdigy May 04 '16 at 19:04
  • 1
    I typical try to make sure my app will run smoothly on the emulator as well as a few devices. You want to be able to accommodate to all of your users and whatever rogue device they have. That said, if you want to double check your app, try putting your app on a phone and enable "Do not keep activites" in Developer Options. This simulates having an device low on memory – VirtualProdigy May 04 '16 at 19:06