关于java:抽象类来摆脱活动中的冗余代码

Abstract class to get rid of redundant code in activities

我创建了一个抽象类来防止在我的每个活动中出现冗余代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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));
        }
      //...
 }

我做这个很好:

1
public class MyActivity extends MyGeneralizedActivity{...}

但现在我必须把MyActivityFragmentActivity扩展。这意味着我不能再从MyGeneralizedActivity扩展了。

现在我想知道是否可以建立一个通用的抽象结构来扩展我的所有活动。

编辑仅仅从FragmentActivity扩展MyGeneralizedActivity并不能解决我的问题。例如,TabActivity将导致同样的问题。

更新对于那些有兴趣在Android中解决相同问题的人,我找到了一个简单的解决方法。存在应用程序类,它提供接口ActivityLifecycleCallbacks等功能。它正是我所需要的,允许我们拦截并为所有活动的重要事件添加一些价值。

您所要做的就是扩展android Application类,并创建一个私有类,在其中实现ActivityLifecycleCallbacks。不要忘记在AndroidManifests文件中添加/重命名应用程序:

1
2
3
4
<application
     android:name=".application.MyApplication"
     //...
/>


这似乎是装饰图案的一个问题。

意图

  • 动态地将附加责任附加到对象上。装饰器为扩展功能提供了一种灵活的子类化替代方案。
  • 客户端通过递归包装核心对象指定的修饰。
  • 把礼物包装起来,放进盒子里,然后把盒子包装起来。

问题

您希望在运行时向单个对象添加行为或状态。继承不可行,因为它是静态的,并且应用于整个类。

结构

规范形式:Decorator Pattern Diagram

具体考虑一下您的案例,由于android api没有为活动定义接口,我们可以跳过一些官僚主义,并以(不是这样)快速和肮脏的方式进行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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!
}

然后,您必须创建一个具体的装饰器并重写相应的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
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));
        }
}

然后你可以这样使用它:

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

因为MyAcitvityDecoratorActivity的一个实例,所以可以适当地传递它。

您甚至可以链接装饰器并更改原始Activity对象,如下所示:

1
2
3
4
5
Activity myActivity = new MyActivityDecorator(
    new AnotherActivityDecorator(
        new TabActivity()
    )
);

由于FragmentActivityMyGeneralizedActivity都是类,而不是接口,因此无法创建属于这两者的子类型的类型。

Java将你限制为单一继承,所以如果你依赖于共享实现,它包含在两个类中,那么你最好的选择是依赖于构图。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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));
    //...
  }

}


如果使用Java 8,可以使用默认方法创建接口。然后,您可以通过这种方式实现多个接口,并获得所需的结果。

详细介绍:在Java 8中使用默认方法与抽象类的接口


请参见FragmentActivity源代码。FragmentActivity扩展了Activity类。我想你应该试试看。

Best of luck.