Вот подборка самых распространенных способов добиться этого :
- Отправить данные внутри намерения
- Статические поля
- HashMap из
WeakReferences
- Сохранять объекты (sqlite, общие настройки, файлы и т. Д.)
TL; DR : существует два способа обмена данными: передача данных в дополнениях к цели или сохранение их в другом месте. Если данные являются примитивами, строками или объектами, определенными пользователем: отправьте их как часть дополнений к намерениям (объекты, определенные пользователем, должны быть реализованы Parcelable
). При передаче сложных объектов сохраняйте экземпляр в одном месте где-нибудь еще и получайте к ним доступ из запущенного действия.
Некоторые примеры того, как и зачем реализовывать каждый подход:
Отправить данные в намерениях
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("some_key", value);
intent.putExtra("some_other_key", "a value");
startActivity(intent);
На втором занятии:
Bundle bundle = getIntent().getExtras();
int value = bundle.getInt("some_key");
String value2 = bundle.getString("some_other_key");
Используйте этот метод, если вы передаете примитивные данные или строки . Вы также можете передавать объекты, которые реализует Serializable
.
Несмотря на соблазн, вы должны подумать дважды перед использованием Serializable
: это подвержено ошибкам и ужасно медленно. Итак, в целом: держитесь подальше,Serializable
если это возможно. Если вы хотите передать сложные пользовательские объекты, взгляните на Parcelable
интерфейс . Его сложнее реализовать, но он значительно выиграл в скорости Serializable
.
Обмен данными без сохранения на диске
Можно обмениваться данными между действиями, сохраняя их в памяти, учитывая, что в большинстве случаев обе операции выполняются в одном и том же процессе.
Примечание: иногда, когда пользователь покидает вашу деятельность (не выходя из нее), Android может решить убить ваше приложение. В таком сценарии у меня были случаи, когда андроид пытается запустить последнее действие, используя намерение, предоставленное до того, как приложение было убито. В этом случае данные, хранящиеся в единственном экземпляре (как вашем, так и Application
), исчезнут, и могут случиться плохие вещи. Чтобы избежать таких случаев, вы либо сохраняете объекты на диск, либо проверяете данные перед их использованием, чтобы убедиться, что они действительны.
Используйте одноэлементный класс
Есть класс для хранения данных:
public class DataHolder {
private String data;
public String getData() {return data;}
public void setData(String data) {this.data = data;}
private static final DataHolder holder = new DataHolder();
public static DataHolder getInstance() {return holder;}
}
Из запущенной деятельности:
String data = DataHolder.getInstance().getData();
Используйте приложение синглтон
Синглтон приложения - это экземпляр, android.app.Application
который создается при запуске приложения. Вы можете предоставить пользовательский, расширив Application
:
import android.app.Application;
public class MyApplication extends Application {
private String data;
public String getData() {return data;}
public void setData(String data) {this.data = data;}
}
Перед началом деятельности:
MyApplication app = (MyApplication) getApplicationContext();
app.setData(someData);
Тогда из запущенной деятельности:
MyApplication app = (MyApplication) getApplicationContext();
String data = app.getData();
Статические поля
Идея в основном такая же, как у синглтона, но в этом случае вы предоставляете статический доступ к данным:
public class DataHolder {
private static String data;
public static String getData() {return data;}
public static void setData(String data) {DataHolder.data = data;}
}
Из запущенной деятельности:
String data = DataHolder.getData();
HashMap из WeakReferences
Та же идея, но позволяющая сборщику мусора удалять объекты, на которые нет ссылок (например, когда пользователь завершает действие):
public class DataHolder {
Map<String, WeakReference<Object>> data = new HashMap<String, WeakReference<Object>>();
void save(String id, Object object) {
data.put(id, new WeakReference<Object>(object));
}
Object retrieve(String id) {
WeakReference<Object> objectWeakReference = data.get(id);
return objectWeakReference.get();
}
}
Перед началом деятельности:
DataHolder.getInstance().save(someId, someObject);
Из запущенной деятельности:
DataHolder.getInstance().retrieve(someId);
Вы можете или не можете передавать идентификатор объекта, используя дополнительные функции намерения. Все зависит от вашей конкретной проблемы.
Сохранять объекты на диске
Идея состоит в том, чтобы сохранить данные на диске перед запуском другого действия.
Преимущества: вы можете запустить действие из других мест и, если данные уже сохранены, оно должно работать просто отлично.
Недостатки: это громоздко и требует больше времени для реализации. Требуется больше кода и, следовательно, больше шансов на появление ошибок. Это также будет намного медленнее.
Вот некоторые из способов сохранения объектов: