Примечания к «Руководству по применению Jetpack»

Модель представления

хранить данные пользовательского интерфейса

Активность/фрагмент только отображает данные и обрабатывает взаимодействие с пользователем.

ViewModel содержит данные пользовательского интерфейса.

жизненный цикл

Реконструкция Activity не повлияет на жизненный цикл ViewModel.

Существует только одна функция жизненного цикла ViewModel onCleared(), и эта функция будет вызываться только тогда, когда страница, представленная Activity, будет уничтожена.
вставьте сюда описание изображения

Контекст цитирования ViewModel

Жизненный цикл ViewModel длиннее, чем у Activity, поэтому не следует хранить ссылку на Activity во ViewModel, иначе это приведет к утечке памяти.

ViewModel не рекомендует вводить Activity, но что, если во ViewModel необходим Context? Можно использовать один из следующих методов: 1.
Использовать 2. Использовать AndroidViewModel, который является подклассом ViewModel, который получает приложение в качестве внутреннего контекста;Context.getApplicationContext()

Создание экземпляра ViewModel

XXXViewModel mXXXViewModel = new ViewModelProvider(this).get(XXXViewModel.class);

Разница между ViewModel и onSaveInstanceState()

  1. Разница в данных
    onSaveInstanceState() может сохранить только небольшой объем данных пользовательского интерфейса, которые можно сериализовать, и не может сохранять большие данные, такие как растровые изображения.
    ViewModel не имеет таких ограничений.

  2. Сохранение данных
    onSaveInstanceState() может сохранить небольшой объем данных пользовательского интерфейса в следующих двух ситуациях:
    ① Процесс приложения завершается из-за ограничений памяти, когда он находится в фоновом режиме.
    ② Изменения конфигурации.

Модели представления могут сохранять данные только в случае уничтожения при изменении конфигурации, а не в завершенных процессах.

LiveData

использовать

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

ViewModel содержит данные пользовательского интерфейса, а Activity/Fragment отвечает за отображение данных. Если данные пользовательского интерфейса изменяются, LiveData уведомляет Activity/Fragment о необходимости обновления данных. Итак, LiveData обычно используется во ViewModel.

основное использование

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

Наблюдайте за данными, упакованными LiveData, с помощью метода LiveData.observe(). И наоборот, когда мы хотим изменить данные, заключенные в LiveData, мы можем сделать это с помощью метода LiveData.postValue()/LiveData.setValue(). postValue() вызывается в потоке, отличном от пользовательского интерфейса, а setValue() вызывается в потоке пользовательского интерфейса.

обновление уведомления

LiveData может отслеживать жизненный цикл страницы, и только тогда, когда страница находится в активном состоянии (Lifecycle.State.STARTED или Lifecycle.State.RESUMED), будет получено уведомление LiveData. Если страница уничтожена (Lifecycle.State. DESTROYED), то LiveData автоматически очистит ассоциации со страницами, что позволит избежать утечек памяти.

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

LiveData.observeForever() используется так же, как и Observe, разница в том, что при изменении данных, независимо от того, в каком состоянии находится страница, она может получать уведомления. Таким образом, вы должны вызвать метод removeObserver() после использования, чтобы удалить наблюдателя и избежать утечек памяти.

ViewModel+LiveData реализует связь между фрагментами.

public class OneFragment extends Fragment {
    
    

	public void onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    
    
		/*
		关键在于ViewModelProvider的构造函数传入的是getActivity()而不是Fragment.this,
		这样才能保证每个Fragment得到的是同一个ViewModel,从而共享LiveData
		*/
		XXXViewModel mXXXViewModel = new ViewModelProvider(getActivity()).get(XXXViewModel.class);
	}
}

//TwoFragment与OneFragment类似

краткое содержание

Суть LiveData — это режим наблюдателя + жизненный цикл восприятия.

Привязка данных

легко использовать

  1. Начать привязку данных
android {
    
    
	……
	dataBinding {
    
    
		enabled = true;
	}
}
  1. Файл макета тегов
    Добавляйте теги за пределами корня файла макета <layout>. Целью этого является указание библиотеке DataBinding создать класс Binding, соответствующий файлу макета.
<layout xmlns:android="http://schemas.android.com/apk/res/android">
	/*
	以下是实际布局
	……
	*/
</layout>
  1. Определить переменные макета
<layout xmlns:android="http://schemas.android.com/apk/res/android">
	<data>
		<variable
			name = "变量名"
			type = "类全名"/>
		/*
		或者使用<import>标签引入类
		<import type = "类全名"/>
		<variable
			name = "变量名"
			type = "类名称"/>
		*/
		
	</data>
	/*
	以下是实际布局
	……
	*/
</layout>
  1. Получить класс привязки
//该方法给Activity设置布局文件的同时,返回Binding类。
XXXBinding mXXXBinding = DataBindingUtil.setContentView(this, R.layout.xxx);
  1. Назначение переменных макета
    Binding предоставляет два метода присвоения значений переменным макета:
    ①Общий метод: XXXBinding.setVariable(BR.变量名, 变量);
    ②Метод назначения для конкретных переменных макета:XXXBinding.set变量名(变量)

  2. Выражение макета
    Формат выражения макета: @{}.
    Например: @{布局变量.字段},@{方法调用的表达式}

<data>
	<import type = "xxx.xxx.TestUtil"/>
	<variable
		name = "book"
		type = "xxx.xxx.Book"/>
</data>

<!-- 在布局中引用静态类-->
<TextView
	android:text="@{TestUtil.getText()}"/>

<TextView
	android:text="@{book.name}"/>

Выражения макета — это гораздо больше, чем просто эти варианты использования.Подробнее см.: Подробное объяснение привязки данных (2) — выражения макета и привязки.

  1. Окончательный вид активности
public class TestActivity extends Activity {
    
    
	protected void onCreate(Bundle savedInstanceState) {
    
    
		super.onCreate(savedInstanceState);
		XXXBinding mXXXBinding = DataBindingUtil.setContentView(this, R.layout.xxx);
		Book book = new Book();
		book.name = "Jetpack应用指南";
		mXXXBinding.setBook(book);
	}
}

привязка событий

DataBinding поддерживает использование выражений макета для обработки ответов на события View.
Конкретный метод: присвойте выражение макета атрибуту события View в файле макета.
Это эквивалентно использованию выражения макета для реализации обратного вызова соответствующего прослушивателя. Эта практика известна как привязка событий .

Соответствие между атрибутами событий и слушателями

Имя атрибута события зависит от имени метода прослушивателя. Например, у View.OnClickListener есть onClick()метод, а у View.OnLongClickListener есть onLongClick()метод, поэтому свойства события — android:onClick, android:onLongClick.
Для события клика, чтобы избежать конфликта нескольких событий клика, Google также определяет специальную обработку событий, например:

Сорт Как настроить прослушиватель свойства привязки
ПоискПросмотр setOnSearchClickListener (View.OnClickListener) Android: onSearchClick
ZoomControls setOnZoomInClickListener(View.OnClickListener) Android: onZoomIn
ZoomControls setOnZoomOutClickListener(View.OnClickListener) Android: onZoomOut

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

эталонный метод

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

public class EventHandler {
    
    

	public void onClickHandle(View view) {
    
    
		System.out.println("按钮被点击了");
	}
}


<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="eventHandler"
            type="xxx.xxx.EventHandler" />
    </data>
    ...
    <Button
           ...
            android:onClick="@{eventHandler::onClickHandle}"
           ... />
    ...
</layout>

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

/*
“引用方法”的监听器创建原理如下伪代码所示
伪代码是在运行时运行的。
*/
xxxBinding.setEventHandler(EventHandler eventHandler) {
    
    
	if(eventHandler != null) {
    
    
		button.setOnClickListener(new OnClickListener() {
    
    
				public void onClick(View view) {
    
    
					eventHandler.onClickHandle(view);
				}
		});
	}
}

привязать прослушиватель

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

public class Tester {
    
    
	
	public boolean testLongClick() {
    
    
		return false;
	}
}

<Button
   ...
   android:onClick="@{()->tester.testLongClick()}"
   ... />

Слушатели привязки допускают пользовательские параметры.

public class Tester {
    
    

	public boolean testLongClick(View v, String info) {
    
    
		Toast.makeText(v.getContext(), info, Toast.LENGTH_LONG).show();
	}
}

<Button
   ...
   android:onClick="@{(view)->tester.testLongClick(view, '你好')}"
   ... />

«Bind Listener» автоматически создаст необходимый прослушиватель и зарегистрирует для него события при компиляции (слушатель создается в начале, и не будет оцениваться, пуста ли переменная макета, пока она не сработает, и никакое выполнение не будет выполнено, если он пустой.работайте)

/*
“绑定监听器”的监听器创建原理如下伪代码所示
伪代码是在编译时运行的。
*/
button.setOnClickListener(new OnClickListener() {
    
    
	public void onClick(View view) {
    
    
		if(tester != null) {
    
    
			tester.testLongClick(view, "你好");
		}});

троичное выражение

Если вам нужно использовать выражение с предикатом (например, троичное выражение), вы можете использовать тип возвращаемого значения, соответствующий прослушивателю, в качестве выражения, например void для атрибута onCLick и Boolean для атрибута onLongClick.

    android:onClick="@{(view)->view.isEnabled()?activity.showSign(view, user):void}"
    android:onLongClick="@{(v)->v.isEnabled()?activity.showSign(user):false}"

Переплет второстепенных страниц

Мы называем страницу, на которую непосредственно ссылается Activity/Fragment, страницей первого уровня, а страница, на которую ссылается метка на странице первого уровня, называется страницей второго уровня.

Как передать переменные макета со страницы первого уровня на страницу второго уровня?

После того , как переменная макета определена в макете первого уровня , переменная может быть не только получена и использована в макете первого уровня, но и стать атрибутом bookпространства имен . Целью этого атрибута является передача переменных макета во вторичный макет.xmlns:app
book

//一级页面
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
	<data>
		<variable
			name = "book"
			type = "xxx.xxx.Book"/>
	</data>

	<LinearLayout
		android:orientation="vertical"
		android:layout_width="match_parent"
		android:layout_height="match_parent">

		<include
			layout="@layout/layout_content"
			app:book="@{book}">
	</LinearLayout>
</layout>

//二级页面
/**
在二级页面layout_content中,需要定义一个与一级页面相同的布局变量,
用来接收传递过来的数据。收到book变量后即可使用该变量了。
*/
<layout xmlns:android="http://schemas.android.com/apk/res/android">
	<data>
		<variable
			name = "book"
			type = "xxx.xxx.Book"/>
	</data>

	<TextView
		……
		android:text="@{book.name}"/>
</layout>

Адаптер привязки

Адаптер привязки (BindingAdapter) предназначен для преобразования выражения атрибута в макете в соответствующий вызов метода для установки значения .
Так называемое значение настройки делится на два типа:
①Установка значения атрибута, например, вызов метода setText().
②Установка прослушивателя событий, например, вызов метода setOnClickListener().
Это также позволяет вам настроить вызывающий метод установки значения и предоставить собственную логику привязки.

BindingAdapter из библиотеки DataBinding.

Многие классы XXXBindingAdapter предоставляются в библиотеке DataBinding, которая позволяет собственным элементам управления Android поддерживать выражения атрибутов.

//DataBinding库下ViewBindingAdapter的部分源码
public class ViewBindingAdapter {
    
    

	@BindingAdapter({
    
    "android:padding"})
	public static void setPadding(View view, float paddingFloat) {
    
    
		final int padding = pixelsToDimensionPixelSize(paddingFloat);
		view.setPadding(padding, padding, padding, padding);
	}
}

рекомендация

отblog.csdn.net/jiejingguo/article/details/118567220
рекомендация