C#: ориентированные на многопотоковое исполнение события

TL; DR

Используйте android.support.v7.widget.Toolbar и просто выполните:

toolbar.inflateMenu(R.menu.my_menu)
toolbar.setOnMenuItemClickListener {
    onOptionsItemSelected(it)
}

Автономная панель инструментов

Большинство предлагаемых решений, таких как setHasOptionsMenu(true), работают только когда родительская активность имеет панель инструментов в своем макете и объявляет ее через setSupportActionBar(). Затем фрагменты могут участвовать в заполнении меню этого точного ActionBar :

Fragment.onCreateOptionsMenu (): инициализировать содержимое стандартного меню опций хоста фрагмента.

Если вам нужна отдельная панель инструментов и меню для одного конкретного фрагмента , вы можете сделать следующее:

menu_custom_fragment.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/menu_save"
        android:title="SAVE" />
</menu>

custom_fragment.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    ...

CustomFragment.kt

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val view = inflater.inflate(layout.custom_fragment, container, false)
    val toolbar = view.findViewById<Toolbar>(R.id.toolbar)
    toolbar.inflateMenu(R.menu.menu_custom_fragment)
    toolbar.setOnMenuItemClickListener {
        onOptionsItemSelected(it)
    }
    return view
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    return when (item.itemId) {
        R.id.menu_save -> {
            // TODO: User clicked the save button
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}

Да, это так просто. Вам даже не нужно переопределять onCreate() или onCreateOptionsMenu().

PS: Это работает только с android.support.v4.app.Fragment и android.support.v7.widget.Toolbar (также обязательно используйте тему AppCompatActivity и тему AppCompat в вашей styles.xml).

5
задан Svish 24 June 2009 в 12:12
поделиться

2 ответа

У использования интерфейса очень много целей.

  1. Использование в полиморфном поведении. Если вы хотите вызвать определенные методы дочернего класса с интерфейсом, имеющим ссылку на дочерний класс.

  2. Наличие контракта с классами для реализации всех методов там, где это необходимо, как и в большинстве случаев с COM-объектами, где класс-оболочка создается для библиотеки DLL, наследующей интерфейс; эти методы вызываются за кулисами, и вам просто нужно их реализовать, но с той же структурой, которая определена в COM DLL, о которой вы можете узнать только через интерфейс, который они предоставляют.

  3. Чтобы уменьшить использование памяти путем загрузки определенных методов в класс. Например, если у вас есть три бизнес-объекта, и они реализованы в одном классе, вы можете использовать три интерфейса.

Например, IUser, IOrder,

4
ответ дан 14 December 2019 в 01:14
поделиться

Вам также необходимо заблокировать, когда вы загружаете обработчик, иначе у вас может не быть последнего значения:

protected void OnProcessingCompleted(ProcessCompletedEventArgs e)
{
    EventHandler<ProcessCompletedEventArgs> handler;
    lock (completedEventLock) 
    {
        handler = ProcessCompleted;
    }
    if (handler != null)
        handler(this, e);
}

Обратите внимание, что это не предотвращает состояние гонки, когда мы решили выполнить набор обработчиков и затем один обработчик отменил подписку. Он все равно будет вызываться, потому что мы загрузили делегат многоадресной рассылки, содержащий его, в переменную обработчика .

Вы не можете многое с этим поделать, кроме как сообщить самому обработчику, что он не должен больше не будет вызываться.

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

5
ответ дан 14 December 2019 в 01:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: