Композиция с android.app.Activity - PullRequest
3 голосов
/ 30 августа 2011

Источник мудрости «Эффективная Ява 2-й» говорит: «Пользуйся композицией по наследству» (пункт 16).Теперь, когда дело доходит до Android Activity, его легко расширить от одного, но вы нарушаете инкапсуляцию, и код может сломаться при изменении суперкласса.Я пытался сочинять.Вот код компонента Activity:

public class SimpleActivity extends Activity{
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView textview = new TextView(this);
        textview.setText("This is the Artists tab");
        setContentView(textview);
    }   
}

Вот составленный.Для методов жизненного цикла каждого действия я вызываю методы forward.

public class ComposedActivity extends Activity {
    private SimpleActivity act;
    public ComposedActivity(){
        act = new SimpleActivity();
    }

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        act.onCreate(savedInstanceState);
    }   
}

Но приложение продолжает аварийно завершать работу из-за: java.lang.NullPointerException.Что я делаю неправильно ?Просто спрашиваю из любопытства.Что вы рекомендуете расширить Activity без наследования?

Ответы [ 3 ]

6 голосов
/ 30 августа 2011

Вы не можете иметь деятельность внутри другой деятельности. Если вы хотите использовать композицию для компонентов Android, взгляните на фрагменты .

Вы можете использовать композицию, не используя фрагменты, просто разделив вашу логику на простые классы Java (POJO), которые не являются компонентами Android. Если им нужен доступ к действию, вы можете передать ссылки на целевое действие в конструкторе. Или еще лучше: пусть ваши действия реализуют какой-то интерфейс, чтобы они содержали ссылку на него, а не на конкретные действия.

1 голос
/ 12 мая 2016

Я написал библиотеку, поддерживающую композицию «Действия и фрагменты». https://github.com/passsy/CompositeAndroid

Вы должны расширить CompositeActivity, и тогда вы сможете добавить плагины, которые имеют те же методы для переопределения, что и само действие.

Пример

public class MainActivity extends CompositeActivity {

    public MainActivity() {
        addPlugin(new DevOptionsPlugin());
    }
}

Плагин добавляет элемент в меню параметров и обрабатывает щелчки

public class DevOptionsPlugin extends ActivityPlugin {

    public static final String DEVELOPER_OPTIONS_TEXT = "Developer options";

    @Override
    public boolean onCreateOptionsMenu(final Menu menu) {
        super.onCreateOptionsMenu(menu);
        menu.add(DEVELOPER_OPTIONS_TEXT);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(final MenuItem item) {
        if (DEVELOPER_OPTIONS_TEXT.equals(item.getTitle())) {
            Intent intent = new Intent(Intent.ACTION_VIEW,
                    Uri.parse("mycompany://appname/devoptions"));
            try {
                // note: simply calling startActivity(intent); is not allowed because the call order 
                // would be different. The code before super.startActivity in this plugin would be executed 
                // first before a plugin added later and is more specialized.
                getActivity().startActivity(intent);
            } catch (ActivityNotFoundException e) {
                Toast.makeText(getActivity(), "Couldn't open Activity", Toast.LENGTH_SHORT).show();
            }
            // not calling super!!!
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}
1 голос
/ 30 августа 2011

У вас есть NullPointerException, потому что SimpleActivity.onCreate() вызывается напрямую ComposedActivity, в то время как предполагается, что он вызывается через Intent. Поэтому, когда Activity, суперкласс SimpleActivity, пытается извлечь Intent, который использовался для его активации, он находит null и вылетает, поскольку это неожиданно.

Вдобавок к этому ComposedActivity простирается Activity, но вы не звонили super.onCreate() с ComposedActivity.onCreate(). Обычно это вызывает следующее исключение:

android.app.SuperNotCalledException: 
    Activity did not call through to super.onCreate()

Но, читая ваш вопрос, вероятно, по ошибке ComposedActivity расширяет Activity. Как я понял вопрос, ComposedActivity не должен наследоваться от Activity, но делегировать все вещи Activity в SimpleActivity.

Так или иначе, и, несмотря на источник мудрости, которым является Эффективная Ява, еще один источник мудрости способствует наследованию от Activity как лучшая практика. Более серьезно, даже если код, который мы находим в руководствах, иногда сомнительный, я думаю, что наследование от Activity - далеко не лучший способ реализации Activity: это было разработано именно таким образом Android.

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