Reputation: 43
I've created a reusable xml layout that looks like this
I would like to use same component on different activities , what i want to do is to create BaseActivityClass
that extends Activity.
public class BaseActivityClass extends Activity {
int layout_id = R.layout.SomeLayout;
final int menu_button_id = R.id.menuButton;
final int save_button_id = R.id.saveButton;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(layout_id);
Button btn = findViewById(menu_button_id);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//this functionality will be same on every child class
}
});
}
}
I would like to extend that class as
public class SomeActivityClass extends BaseActivityClass {
int layout_id = R.layout.SomeOtherLayout;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
There is no constructor class for Activity.On intent call only class name is referenced. And subclass cannot change super class variables(hiding).
I dont want to copy paste same code that is in BaseActivityClass
into other classes.
A wrapper class might solve the problem but that seems too sloppy imo.
How can i solve this design issue? I am free to comment on any idea
Upvotes: 2
Views: 105
Reputation: 10185
Sounds like you want the base class to control the main container layout and allow the derived class to provide a "content" layout. Is that correct? If so, you can use this pattern:
Step 1 - Add a ViewStub
to your base layout. Some pseudocode to give you the idea:
<ConstraintLayout>
<!-- Common Stuff -->
<Button id="menu">
<Button id="save">
<!-- "Content" area to be filled by derived classes -->
<ViewStub id="viewStub" />
</ConstraintLayout>
Step 2 - Update your base layout to provide a way to inflate content into the "content area". Some Pseudocode:
public abstract class BaseActivityClass extends Activity {
int layout_id = R.layout.SomeLayout;
final int menu_button_id = R.id.menuButton;
final int save_button_id = R.id.saveButton;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(layout_id);
Button btn = findViewById(menu_button_id);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//this functionality will be same on every child class
}
});
// Get the ViewStub, set the derived class's content layout on it and inflate it,
// thereby displaying the derived class's view layout within the base class's
// "content area"
ViewStub vs = findViewById(viewStub);
vs.setLayout(getContentLayoutId());
vs.inflate();
}
// Define abstract method that all derived classes must implement to provide
// the id of the layout to show in the "content area"
@LayoutRes
public abstract int getContentLayoutId();
}
Step 3 - Update your derived class to provide the layout you want to display. Some pseudocode:
public class SomeActivityClass extends BaseActivityClass {
int layout_id = R.layout.SomeOtherLayout;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
@LayoutRes
public int getContentLayoutId() { return layout_id; }
}
Now when SomeActivityClass
is created, it calls the super class onCreate
which inflates your base layout and then asks the derived class for it's main content layout that it shoves into the "content area".
I've used this pattern on my projects and it works quite well.
Another option is to simply pass the layout ID via the super class constructor. If the base Activity is abstract
it will never be instantiated and doesn't have to adhere to the zero-arg constructor rule. Only your derived class does. So you can do something like this:
public abstract class BaseActivityClass extends Activity {
private final int mContentLayoutId;
protected BaseActivityClass(int contentLayoutId) {
mContentLayoutId = contentLayoutId;
}
protected void onCreate(Bundle state) {
// Same code to load ViewStub, but use mContentLayoutId instead
}
}
public SomeOtherActivity extends BaseActivity {
public SomeOtherActivity() {
super(R.layout.SomeOtherLayout); // Call super with derived layout
}
}
Hope that helps!
Upvotes: 1