C ++ включает полезные общие функции, такие как std::for_each
и std::transform
, что может быть очень удобно. К сожалению, они также могут быть довольно громоздкими в использовании, особенно если functor , который вы хотите применить, уникален для конкретной функции.
#include
#include
namespace {
struct f {
void operator()(int) {
// do something
}
};
}
void func(std::vector& v) {
f f;
std::for_each(v.begin(), v.end(), f);
}
Если вы используете только f
один раз и в этом конкретном месте кажется излишним писать целый класс, просто чтобы сделать что-то тривиальное и одно.
В C ++ 03 у вас может возникнуть соблазн написать что-то вроде следующего, чтобы сохранить functor local:
void func2(std::vector& v) {
struct {
void operator()(int) {
// do something
}
} f;
std::for_each(v.begin(), v.end(), f);
}
однако это недопустимо, f
не может быть передано функции template в C ++ 03.
C ++ 11 вводит lambdas, чтобы вы могли написать встроенный анонимный функтор для замены struct f
. Для небольших простых примеров это может быть более чистым для чтения (он хранит все в одном месте) и потенциально проще поддерживать, например, в простейшей форме:
void func3(std::vector& v) {
std::for_each(v.begin(), v.end(), [](int) { /* do something here*/ });
}
Лямбда-функции - это просто синтаксический сахар для анонимных функторов .
В простых случаях для вас выводится тип возврата лямбда, например:
void func4(std::vector& v) {
std::transform(v.begin(), v.end(), v.begin(),
[](double d) { return d < 0.00001 ? 0 : d; }
);
}
, однако, когда вы начинаете писать больше сложный lambdas, вы быстро столкнетесь с случаями, когда тип возврата не может быть выведен компилятором, например:
void func4(std::vector& v) {
std::transform(v.begin(), v.end(), v.begin(),
[](double d) {
if (d < 0.0001) {
return 0;
} else {
return d;
}
});
}
Чтобы разрешить это, вам разрешено явно указывать тип возврата для лямбда-функции, используя -> T
:
void func4(std::vector& v) {
std::transform(v.begin(), v.end(), v.begin(),
[](double d) -> double {
if (d < 0.0001) {
return 0;
} else {
return d;
}
});
}
До сих пор мы не использовали ничего, кроме того, что было передано лямбда внутри него, но мы также можем использовать другие переменные, в пределах лямбда. Если вы хотите получить доступ к другим переменным, вы можете использовать предложение capture ([]
выражения), которое до сих пор не использовалось в этих примерах, например:
void func5(std::vector& v, const double& epsilon) {
std::transform(v.begin(), v.end(), v.begin(),
[epsilon](double d) -> double {
if (d < epsilon) {
return 0;
} else {
return d;
}
});
}
Вы можете выполнять захват обоими ссылку и значение, которые вы можете указать с помощью &
и =
соответственно:
[&epsilon]
захват по ссылке [&]
захватывает все переменные, используемые в lambda по ссылке [=]
фиксирует все переменные, используемые в лямбда по значению [&, epsilon]
захватывает переменные, такие как [& amp;], но epsilon по значению [=, &epsilon]
захватывает переменные, такие как [=], но epsilon по ссылке Порожденный operator()
по умолчанию const
, с импликацией, которая захватывает, будет const
когда вы обращаетесь к ним по умолчанию. Это приводит к тому, что каждый вызов с одним и тем же входом даст тот же результат, однако вы можете пометить лямбда как mutable
, чтобы запросить, что созданный operator()
не const
.
Ну, у меня есть несколько идей, но я не знаю, что они ищут.
Вы можете использовать службу, которая содержит все данные, а затем просто привязать ваши действия к службы для восстановления данных.
Или упаковывайте свои данные в сериализуемые или разборчивые и присоединяйте их к пакету и передайте пакет между действиями.
Это может быть совсем не то, что ваш ищет, но вы также можете попробовать использовать SharedPreferences или предпочтение в целом.
В любом случае, дайте мне знать, что вы решите.
Здесь компиляция наиболее распространенных способов достижения этого :
WeakReferences
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
.
. Можно обмениваться данными между действиями, сохраняя их в памяти учитывая, что в большинстве случаев оба действия выполняются в одном и том же процессе.
Примечание: иногда, когда пользователь покидает вашу деятельность (не покидая ее), 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 String setData(String data) {DataHolder.data = data;}
}
Из запущенной деятельности:
String data = DataHolder.getData();
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);
Возможно, вам может понадобиться передать идентификатор объекта с помощью дополнительных настроек намерения. Все зависит от вашей конкретной проблемы.
Идея состоит в том, чтобы сохранить данные на диске перед запуском другого действия.
Преимущества: вы можете запустить активность из других мест, и если данные уже сохранены, это должно работать нормально.
Недостатки: это громоздко и требует больше времени для реализации. Требуется больше кода и, следовательно, больше шансов ввести ошибки.
Некоторые способы сохранения объектов включают в себя:
setResult
. Кроме того, в этом случае вторичная активность должна быть вызвана с использованием метода startActivityForResult
.
– Cristian
6 December 2012 в 19:24
Activity
повсюду, а в своем onCreate()
проверьте любое статическое поле синглтона, которое вы заполняете при запуске приложение. Если это поле пуст, вернитесь к началу действия, используя FLAG_ACTIVITY_CLEAR_TASK
или BroadcastReceiver
, чтобы убить другие действия.
– Janosch
19 June 2014 в 17:52
Все вышеупомянутые ответы велики ... Я просто добавляю один, о котором никто еще не упомянул о сохранении данных через действия, а также о том, чтобы использовать встроенную базу данных SQLite для Android, чтобы сохранить релевантные данные ... На самом деле вы может поместить вашу базу данных в состояние приложения и вызвать ее по мере необходимости во время активации. Или просто создать вспомогательный класс и сделать вызовы БД при необходимости ... Просто добавив еще один слой для вас, чтобы рассмотреть ... Но все остальные ответов было бы достаточно ... Действительно просто предпочтение
«Однако я хочу поделиться большим количеством переменных, а некоторые могут быть довольно большими, поэтому я не хочу создавать их копии, как описано выше».
blockquote>Это не делает создайте копию (особенно с помощью String , но даже объекты проходят по значению ссылки, а не по самому объекту, и такие же, как у получателя, удобны в использовании - возможно, лучше использовать, чем другие средства потому что они распространены и хорошо поняты). Более старые «мифы о производительности», такие как не использование геттеров и сеттеров, по-прежнему имеют некоторую ценность, но также были обновлены в документах .
Но если вы не хотите этого делать, вы можете просто сделать переменные общедоступными или защищенными в GlobalState и получить к ним доступ напрямую. И вы можете сделать статический синглтон, поскольку объект приложения JavaDoc указывает :
Как правило, нет необходимости в подклассе Application. В большинстве случаев статические синглтоны могут обеспечивать такую же функциональность более модульным способом. Если вашему singleton нужен глобальный контекст (например, для регистрации широковещательных приемников), функции для его получения можно получить контекст, который внутренне использует Context.getApplicationContext () при первом конструировании singleton.
blockquote>Использование данных Intent , так как другие ответы здесь - это еще один способ передачи данных, но он обычно используется для небольших данных и простых типов. Вы можете передавать более сложные или более сложные данные, но это более активно, чем просто использование статического одиночного. Объект Application по-прежнему остается моим личным фаворитом для совместного использования более крупных / более сложных несовместимых данных между компонентами Android-приложений (поскольку он имеет четко определенный жизненный цикл в приложении для Android).
Кроме того, как отмечали другие, если данные становятся очень сложными и должны быть постоянными , вы также можете использовать SQLite или файловую систему.
Предполагая, что вы вызываете активность два из одного действия с использованием намерения. Вы можете передать данные с помощью намерения.putExtra (),
. Возьмите это для справки. Отправка массивов с помощью Intent.putExtra
Надеюсь, это то, что вы хотите.
Есть разные способы обмена данными между действиями
1: Передача данных между действиями с использованием Intent
Intent intent=new Intent(this, desirableActivity.class);
intent.putExtra("KEY", "Value");
startActivity(intent)
2: Использование статического ключевого слова, определение переменной как public static и использование любой, где в проекте
public static int sInitialValue=0;
используется в любом месте проекта, используя classname.variableName;
3: используя Database
, но его бит длительный процесс, вы должны используйте запрос для вставки данных и итерации данных с помощью курсора, когда это необходимо. Но нет возможности потерять данные без очистки кеша.
4: Использование общих настроек
намного проще, чем база данных. но есть какое-то ограничение, вы не можете сохранить объекты ArrayList, List и custome.
5: Создать геттер-сеттер в классе Aplication и получить доступ к любому где в проекте.
private String data;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
здесь установлено и получить от действий
((YourApplicationClass)getApplicationContext()).setData("abc");
String data=((YourApplicationClass)getApplicationContext()).getData();
И если вы хотите работать с объектом данных, эти два очень важны:
public class User implements Parcelable
Обмен данными между примерами активности, передающими электронное письмо после входа в систему
«email» - это имя, которое может использоваться для ссылки на значение для запрашиваемой деятельности
1 Код на страница входа в систему
Intent openLoginActivity = new Intent(getBaseContext(), Home.class);
openLoginActivity.putExtra("email", getEmail);
2 на домашней странице
Bundle extras = getIntent().getExtras();
accountEmail = extras.getString("email");
Вы можете расширить класс и тег Application для любых объектов, которые вы там хотите, затем они доступны в любом месте вашего приложения
Использование хешмапа слабого ссылочного подхода, описанного выше, и в http://developer.android.com/guide/faq/framework.html кажется проблематичным для меня. Как восстанавливаются целые записи, а не только значение карты? В какой области вы его распределяете? Поскольку инфраструктура контролирует жизненный цикл Activity, при наличии одной из участвующих в ней Деяний, она подвергает риску ошибки времени выполнения, когда владелец уничтожается до своих клиентов. Если приложение принадлежит ему, некоторые действия должны явно удалить запись, чтобы избежать того, чтобы хэш-файл не включался в записи с действительным ключом и потенциально сфальсифицированной собранной слабой ссылкой. Кроме того, что должен делать клиент, когда значение, возвращаемое для ключа, является нулевым?
Мне кажется, что WeakHashMap, принадлежащий Приложению или в одном сингле, является лучшим выбором. Доступ к значению на карте осуществляется с помощью ключевого объекта, и когда нет сильных ссылок на ключ (т. Е. Все действия выполняются с ключом и на что он сопоставляется), GC может восстановить запись карты.
Если вы намерены вызвать другие действия из текущей Деятельности, вы должны использовать намерения . Ваш фокус может быть меньше на сохраняющихся данных, чем на совместном использовании его по мере необходимости.
Однако, если вам действительно необходимо сохранить эти значения, вы можете перенести их в какой-то структурированный текстовый файл или базу данных на локальном хранилище. Файл свойств, файл XML или файл JSON могут хранить ваши данные и легко анализироваться во время создания активности. Не забывайте также, что у вас есть SQLite на всех устройствах Android, поэтому вы можете хранить их в таблице базы данных. Вы также можете использовать карту для хранения пар ключ-значение и сериализации карты для локального хранилища, но это может быть слишком громоздким, чтобы быть полезным для простых структур данных.
Выполняйте то, что вам нужно сделать Google! здесь: http://developer.android.com/resources/faq/framework.html#3
Что вы можете использовать:
То, что вы выбираете, зависит от ваших потребностей. Вероятно, вы будете использовать несколько способов, когда у вас будет «много»
MAIN
. После смерти процесса вы перезапускаете все действия, открытые в последний раз, и это может быть страница с подробной информацией, где-то в приложении.
– EpicPandaForce
19 June 2017 в 17:07