Android Активность многократного использования - PullRequest
1 голос
/ 22 февраля 2020

Я создал макет многократного использования xml, который выглядит следующим образом:

enter image description here

Я хотел бы использовать один и тот же компонент в различных действиях, что Я хочу сделать, это создать BaseActivityClass, который расширяет 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
        }
       });
   }
}

Я хотел бы расширить этот класс как

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

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

Нет класса конструктора для Activity.On намерения ссылка только на имя класса И подкласс не может изменить переменные суперкласса (скрытие).

Я не хочу копировать и вставлять тот же код, который находится в BaseActivityClass, в другие классы. Класс-обертка может решить проблему, но это выглядит слишком небрежно, imo.

Как я могу решить эту проблему дизайна? Я свободен комментировать любую идею

1 Ответ

1 голос
/ 22 февраля 2020

Звучит так, будто вы хотите, чтобы класс 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, который раздувает ваш базовый макет, а затем запрашивает производный класс для основного макета контента, который он вставляет в " область содержимого ".

Я использовал этот шаблон в своих проектах, и он работает довольно хорошо.

Другой вариант - просто передать идентификатор макета через конструктор суперкласса. Если базовая активность равна 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
    }
}

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...