Java – Class becoming God Object what pattern to use

androidcode-qualitydesign-patternsjavasingle-responsibility

I am developing Android app and my MainActivity is becoming God Object.
By the way native Activity class implementation is some sort of God Object already.
The problem is that my activity class is growing and growing.
Let me explain class responsibilites, for those who are not familiar with android.
Activity is like a screen with it's UI, lifecycle, functionality to communicate with OS.
Drawer is part of UI that brings to the activity side menu for navigation in the app.
What is the problem.

public abstract class MainActivity extends SingleFragmentToolBarActivity<T> implements Drawer.OnDrawerItemClickListener {
    private static final int PROFILE_HEADER_IDENTIFIER = 200;
    private float mDisplayDpWidth;
    private float mDisplayDpHeight;
    private Drawer.Result mNavigationDrawer;
    private AccountHeader.Result mAccountHeader;
    private double mDrawerWidthFactor = 0.9;
    private double mDrawerHeaderHeightFactor = 0.3;
    private IProfile<ProfileDrawerItem> mGuestProfile;
    private IProfile<ProfileDrawerItem> mLoggedInProfile;
    private boolean userIsLogged = false;
    public Drawer.Result getNavigationDrawer() {
        return this.mNavigationDrawer;
    }
    private AccountHeader.Result geAccountHeader() {
        return this.mAccountHeader;
    }
    private static final int PROFILE_SETTING = 1;
    private final AccountHeader.OnAccountHeaderSelectionViewClickListener mHeaderSelectionViewClickListener = new AccountHeader.OnAccountHeaderSelectionViewClickListener(.....);
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setUpNavigationDrawer(savedInstanceState);
    }

    private void setUpNavigationDrawer(Bundle savedInstanceState) {
        DrawerImageLoader.init(new DrawerImageLoader.IDrawerImageLoader() {
            @Override
            public void set(ImageView imageView, Uri uri, Drawable placeholder) {
                Picasso.with(imageView.getContext()).load(uri).placeholder(placeholder).into(imageView);
            }

            @Override
            public void cancel(ImageView imageView) {
                Picasso.with(imageView.getContext()).cancelRequest(imageView);
            }

            @Override
            public Drawable placeholder(Context ctx) {
                return null;
            }
        });
        getDisplayMetrics();
        mGuestProfile = buildGuestProfile();
        mAccountHeader = buildNavigationHeader(savedInstanceState);
        mNavigationDrawer = buildDrawer(savedInstanceState);
    }
    protected Drawer.Result buildDrawer(Bundle savedInstanceState) {
     Drawer drawer =  new Drawer(this)
            .withActivity(this);
    ........
    }
    protected List<IProfile> getProfileItemList() {
    ......        
    }
    protected AccountHeader.Result buildNavigationHeader(Bundle savedInstanceState) {
    ......
    }
    private ProfileDrawerItem buildGuestProfile() {
        .......
    }
    private ProfileDrawerItem buildLoggedInProfile(UserBean userBean) {
        .......
    }
    private void getDisplayMetrics() {
       .....
    }
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l, IDrawerItem iDrawerItem) {
     ......
    }

    protected Drawer addItemsIntoDrawer(Drawer buildDrawer) {
        ......
    }
    public void setDrawerWidthFactor(double factor) {
      ......
    }
    public void setDrawerHeaderHeightFactor(double factor) {
      ......
    }

This is only declaration of some methods and class members.
This code above is ONLY for setting navigation drawer in my MainActivity, there will be quite more code in the future here for communicating with services and so on, if to left this as it is, soon I will get class with millions line of code, tons of class members and ton of methods.

Ho to solve this problem, what pattern can be acceptable in this way.
Setting drawer requires reference to the Activity.
I have some ideas how to solve this problem.
Use strategy pattern create interface with all these methods responsible for setting navigation drawer, but how can I pass reference to the activity into the interface implementation in this case I have to create not interface but abstract class and pass reference to the Activity into it's constructor.
This will work, but I still think that it is not perfect, clean solution.

Please suggest what can I do to stop class growing.

EDIT

There is only small responsibility of my activity, there will be more important responsibilities in the future, so I have to get rid of writing a lot initialization code. I haven't post body of methods (300 lines of code). I have found one possible way here is to create some abstract class with basic methods and than create implementation and just use it in my activity when I need this.And in this case it will be possible to change it in runtime (before view has been inflated).

Best Answer

You could create list of classes responsible for each operation, where and when it makes sense for example,

public abstract class MainActivity extends SingleFragmentToolBarActivity<T> implements Drawer.OnDrawerItemClickListener {
    ....

    private void setUpNavigationDrawer(Bundle savedInstanceState) {
        NavigationDrawer drawer = new NavigationDrawer(this,savedInstanceState);  
        drawer.setup();
    }
}

Here you could move logic for each operation (in this example it's NavigationDrawer) to own class where it takes care of the operation.

Related Topic