Abstract class to get rid of redundant code in activities

主宰稳场 提交于 2020-01-02 08:55:12

问题


I created an abstract class to prevent redundant code in each of my activities.

public abstract class MyGeneralizedActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }

        @Override
        public void attachBaseContext(Context newBase) {
            super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
        }
      //...
 }

I was perfectly fine by doing this:

public class MyActivity extends MyGeneralizedActivity{...}

But now I got to the point where I have to extend MyActivity from FragmentActivity. That means I can't extend from MyGeneralizedActivity anymore.

Now I am wondering if it's possible to set up a general abstract structure to extend all of my activities.

EDIT
Just by extending MyGeneralizedActivity from FragmentActivity won't solve my problem. e.g. TabActivity will lead to the same issue.

UPDATE
For those who may be interested in solving the same problem in Android I've found a simple workaround. There exist the Application class, which provides, among other things, the interface ActivityLifecycleCallbacks. It does exactly what I need allowing us to intercept and add some value into important events for all activities.

All you have to do is to extend the Android Application Class and create a private class within which implements ActivityLifecycleCallbacks.
Don't forget to add/rename your Application in your AndroidManifests file:

<application
     android:name=".application.MyApplication" 
     //...
/>

回答1:


As both FragmentActivity and MyGeneralizedActivity are classes and not interfaces there is no way to create a type that is a subtype of both.

Java limits you to single inheritance, so if you're dependent on sharing implementation that's included in two classes, your best bet here is relying on composition instead.

For example:

public class MyActivity extends Activity { 
  FragmentActivity fragmentActivity;
  MyGeneralizedActivity myGeneralizedActivity;

  public MyActivity(FragmentActivity fragmentActivity, MyGeneralizedActivity myGeneralizedActivity) {
    this.fragmentActivity = fragmentActivity;
    this.myGeneralizedActivity = myGeneralizedActivity;
  }


  @Override
  protected void onCreate(Bundle savedInstanceState) {
    this.fragmentActivity.onCreate(savedInstanceState);
    this.myGeneralizedActivity.onCreate(savedInstanceState);
    //...
  }

  @Overridepublic void attachBaseContext(Context newBase) {
    this.fragmentActivity.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
    this.myGeneralizedActivity.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
    //...
  }

}



回答2:


This seems like a problem for the Decorator Pattern.

Intent

  • Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
  • Client-specified embellishment of a core object by recursively wrapping it.
  • Wrapping a gift, putting it in a box, and wrapping the box.

Problem

You want to add behavior or state to individual objects at run-time. Inheritance is not feasible because it is static and applies to an entire class.

Structure

The canonical form:

Thinking specifically about your case, since Android API does not define an interface for Activity, we could skip some bureaucracy and just do it in the (not so) quick and dirty way:

abstract public class ActivityDecorator extends Activity {
    protected Activity original;

    public MyAcitvityDecorator(Activity original) {
        this.original = original;
    }

    protected void onCreate(Bundle savedInstanceState) {
        this.original.onCreate(savedInstanceState);
    }

    /* ... Because there is no better way of doing it in Java, you should do
     * this for every method in the Activity class: delegate the execution of 
     * the method to the original activity object.
     * Yes, there is A LOT of methods!
}

Then you must create a concrete decorator and override the due methods:

class MyActivityDecorator extends ActivityDecorator {
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            this.original.onCreate(savedInstanceState);
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }

        @Override
        public void attachBaseContext(Context newBase) {
            this.original.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
        }
}

Then you can use it like this:

Activity myActivity = new MyActivityDecorator(new Activity());

Because MyAcitvityDecorator is an instance of Activity, you can pass it around seemlessly.

You could even chain decorators and change the original Activity object like this:

Activity myActivity = new MyActivityDecorator(
    new AnotherActivityDecorator(
        new TabActivity()
    )
);



回答3:


See in FragmentActivity source code. FragmentActivity extends Activity class. I think you should try and see.

Best of luck.




回答4:


You can create a interface with default method if using Java 8. Then you can implement multiple interfaces this way and get desired result.

Refer for details: Interface with default methods vs Abstract class in Java 8



来源:https://stackoverflow.com/questions/34517555/abstract-class-to-get-rid-of-redundant-code-in-activities

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!