1

I'm trying to reduce the double effort of using the duplicate code. I searched on the google but didn't found about it that how we can reduce the duplication of code in android. May be this question could be stupid but I want the clarification.

1) The first thing I want to ask is that how we can reuse the same code in the multiple activity which are being using in overriden method as onBackPressed() onOptionsItemSelected() and so on. Here is the code which I'm currently writing in the onBackPressed() method.

@Override
public void onBackPressed(){
    if(this.mDrawerLayout.isDrawerOpen(GravityCompat.START)){
        this.mDrawerLayout.closeDrawer(GravityCompat.START);
    }else{
        super.onBackPressed();
    }
}

For this approache I get the suggestion from this question to make the base activity then override this method after that extends other activities from that BaseActivity. But how I can pass the mDrawerLayout field in the BaseActivity? how I can use findViewById() on that base activity to access the xml widgets to access in the overriden method as currently using mDrawerLayout layout.

Example in code.

public BaseActivity extends AppCompatActivity{

    private DrawerLayout mDrawerLayout; // how to initialize it? where to call findViewById?

    @Override
    public void onBackPressed(){
        if(this.mDrawerLayout.isDrawerOpen(GravityCompat.START)){
            this.mDrawerLayout.closeDrawer(GravityCompat.START);
        }else{
            super.onBackPressed();
        }
    }
}

The same question for the onOptionsItemSelected() mean menu item actions.

2) The second duplication I'm facing about hundred of time is startActivity() I have to write Intent then add the extra data if required than use that Intent. so about 2 to 3 lines I have to write again and again.

3) This thing is about the XML, I'm using the value 5dp or 10dp or 10sp or other dimen values in the XML file which are repeating a lot of time. So I want to ask is this approach will be Ok?

<dimen name="ten_dp">10dp</dimen>
android:layout_margin="@dimen/ten_dp"

Mean declare the dp value then use that in the XML.

Edited:

4) This problem I have faced now. I'm using the same toolbar in all activities and after adding it in XML layout I have to write this code.

private void setupToolbar(){
        setSupportActionBar(mainToolbar);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
        }
    }

But I have to re-write/copy the code in all activities. What is the solution of this problem?

Asif Mushtaq
  • 3,658
  • 4
  • 44
  • 80

2 Answers2

0

1) For your first question, you'd have to have mDrawerLayout in your BaseActivity, then you'd attach your child activity's DrawerLayout into that field on the child activity's onCreate():

super.mDrawerLayout = findViewById(R.id.drawer_layout)

You can also do that for other @Override methods, such as onOptionsItemSelected().

Example based on your BaseActivity class:

public class MainActivity extends BaseActivity {

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

        mDrawerLayout = findViewById(R.id.drawer_layout);
    }
}

Also, make your BaseAcitivity abstract to avoid the "add to manifest warning":

public abstract class BaseActivity extends AppCompatActivity

2) As for your second question, I'd say that in your BaseActivity you could have a public method called getIntent() which would return a common Intent object. You'd then call that method from your child Activity.

You can pretty much have any method with common functionalities on your BaseActivity.

3) From my personal experience, it is counterproductive to declare resource values that does not represent the purpose of itself, such as yours: <dimen name="ten_dp">10dp</dimen>. I'd rather name it based on a representative use, such as <dimen name="activity_margin">10dp</dimen> or whatever.

It is a good practice indeed to have all your hardcoded values (strings, dimens, colors, etc) on your XML resources, you just need to give them significant names (treat them as variable names).

Edit:

4) Add that method into your BaseActivity and pass the Toolbar as a param:

private void setupToolbar(Toolbar mainToolbar){
    setSupportActionBar(mainToolbar);
    ActionBar actionBar = getSupportActionBar();
    if (actionBar != null) {
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
    }
}

Then, you can call it from your MainActivity as:

Toolbar mainToolbar = findViewById(R.id.main_toolbar);
setupToolbar(mainToolbar);
Lucas Cabrales
  • 2,073
  • 1
  • 12
  • 21
  • I have updated my question with other problem and the code example for the problem number 1. – Asif Mushtaq Apr 18 '18 at 19:03
  • Also If I add the BaseActivity that ask me to register in the AndroidManifest.xml file. – Asif Mushtaq Apr 18 '18 at 19:09
  • Updated my answer in regards to your comments. And about the warning on your AndroidManifest.xml file, just add "abstract" to your BaseActivity – Lucas Cabrales Apr 18 '18 at 19:14
  • what if I declare the Toolbar in the BaseActivity and initialize toolbar same as the mDrawerLayout? – Asif Mushtaq Apr 18 '18 at 19:34
  • So now two lines are duplicating in all activities. `mainToolbar = findViewById(R.id.mainToolbar); mDrawerLayout = findViewById(R.id.drawer_layout);` any more perfect solution? I have found this one. Override `onCreate` method in the base activity then call the `super.onCreate` in the child activity after setting `setContentView()` – Asif Mushtaq Apr 18 '18 at 19:42
  • If you do that, then all of your activities that extend from `BaseActivity` would need to have those two views, otherwise you'd get a `NullPointerException`. – Lucas Cabrales Apr 18 '18 at 19:46
  • I know about that. All Activities must have the Toolbar and Drawer. – Asif Mushtaq Apr 18 '18 at 19:47
0

1- How to get reference to the drawer: If all activities have drawer in its xml, and with the same Id, then you can use findViewById in BaseActivity.

protected DrawerLayout drawerLayout;
protected void initNavDrawer() {

    drawerLayout = findViewById(R.id.drawer);

}

The BaseActivity is actually the current running activity, So findViewById is totally fine but make sure you have the drawer in all activity, else you will face NullPointerException

2- For starting activity, In each activity I add a static method which opens the activity

    public static void openForEdit(@NonNull Activity context, @NonNull Order order, int requestCode) {
    Intent editOrderIntent = new Intent(context, EditOrderActivity.class);
    editOrderIntent.putExtra(ORDER_TAG, order);
    editOrderIntent.putExtra(EDIT_TAG, true);
    context.startActivityForResult(editOrderIntent, requestCode);
}

You can make more than one method if needed. Then wherever you want to open the activity just call the static method

MyActivity.open(//passing parameters);

3- About the third point I didn't get exactly your point, But just for clarification: You need to create new xml file called dimens.xml, then you declare your dimens

4- You can put this method in BaseActivity and call it from onCreate in BaseActivity

Omar HossamEldin
  • 3,033
  • 1
  • 25
  • 51
  • 1) - how? any code example? also android hint me to declare the BaseActivity in the AndroidManifest.xml file. – Asif Mushtaq Apr 18 '18 at 19:11
  • Make the BaseActivity abstract class, and don't declare it in Manifest, because you will never open BaseActivity itself – Omar HossamEldin Apr 18 '18 at 19:13
  • Great, I'm now managing everything in the BaseActivity, but one problem I'm facing, I have to call super.onCreate() after the setContentView(). I'm initializing `mDrawerLayout` & `toolbar` in the BaseActivity onCreate. So I have to write `setContentView(R.layout.activity_main); super.onCreate(savedInstanceState);`. Then BaseActivity will be able to call `findViewById()`, for both variables. – Asif Mushtaq Apr 18 '18 at 19:46
  • Do every Activity have the same layout, or different layouts? – Omar HossamEldin Apr 18 '18 at 20:19
  • If different layouts, then you will have to call the method initializing `mDrawerLayout` & `toolbar`, in `onCreate` method of every activity extends the base activity – Omar HossamEldin Apr 18 '18 at 20:22