【问题标题】:Android Activity ReusabilityAndroid Activity 可重用性
【发布时间】:2020-06-06 17:52:12
【问题描述】:

我创建了一个看起来像这样的可重用 xml 布局

我想在不同的活动上使用相同的组件,我想做的是创建扩展活动的BaseActivityClass

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
        }
       });
   }
}

我想将该类扩展为

public class SomeActivityClass extends BaseActivityClass {
    int layout_id = R.layout.SomeOtherLayout;

    protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
    }
}

Activity 没有构造函数类。在意图调用时仅引用类名。 并且子类不能改变超类变量(隐藏)。

我不想将BaseActivityClass 中的相同代码复制粘贴到其他类中。 包装类可能会解决问题,但 imo 似乎太草率了。

我该如何解决这个设计问题? 我可以对任何想法发表评论

【问题讨论】:

  • Layout xml can include other xml - 你有没有考虑过只用布局和“包含”来实现组合。
  • 感谢@Andy 的输入,我正在使用include,但问题是我的模板有按钮,并且每次使用时按钮事件都是相同的,我不想在不同的@987654329 上复制相同的事件@类。

标签: java android oop code-reuse


【解决方案1】:

听起来您希望 base 类控制主容器布局并允许 派生 类提供“内容”布局。那是对的吗?如果是这样,您可以使用此模式:

第 1 步 - 在基本布局中添加 ViewStub。一些伪代码给你的想法:

<ConstraintLayout>
   <!-- Common Stuff -->
   <Button id="menu">
   <Button id="save">

   <!-- "Content" area to be filled by derived classes -->
   <ViewStub id="viewStub" />

</ConstraintLayout>

第 2 步 - 更新您的基本布局以提供一种将内容膨胀到“内容区域”的方法。一些伪代码:

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();
}

第 3 步 - 更新您的派生类以提供您想要显示的布局。一些伪代码:

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; }
}

现在,当 SomeActivityClass 创建时,它会调用超类 onCreate,它会扩展您的基本布局,然后向派生类询问它推入“内容区域”的主要内容布局。

我在我的项目中使用了这种模式并且效果很好。


另一种选择是通过超类构造函数简单地传递布局 ID。如果基础 Activity 是abstract,它将永远不会被实例化并且不必遵守零参数构造函数规则。只有您的派生类可以。所以你可以这样做:

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
    }
}

希望有帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-25
    • 2020-04-09
    • 2013-09-28
    相关资源
    最近更新 更多