在活动之间共享数据的最佳方式是什么? [英] What's the best way to share data between activities?

查看:142
本文介绍了在活动之间共享数据的最佳方式是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个活动,它是整个应用程序中使用的主要活动,它有许多变量。我有两个其他活动,我希望能够使用第一个活动的数据。
现在我知道我可以这样做:

  GlobalState gs =(GlobalState )getApplication(); 
String s = gs.getTestMe();

但是我想分享很多变量,有些可能比较大,所以我不想要如上所述创建它们的副本。



有没有办法直接获取和更改变量而不使用get和set方法?我记得在Google开发网站上阅读了一篇文章,说不建议在Android上使用此功能。

解决方案

这里有一个< a href =http://developer.android.com/guide/faq/framework.html#3 =noreferrer>最常见的实现方法:




  • 在意图内发送数据

  • 静态字段

  • 的HashMap WeakReferences

  • 持久对象(sqlite,分享首选项,文件等)



TL; DR :有两种共享数据的方式:在intent的附加内容中传递数据或将其保存在其他地方。如果数据是基元,字符串或用户定义的对象:将其作为意图附加内容的一部分发送(用户定义的对象必须实现 Parcelable )。如果传递复杂对象,则将实例保存在其他地方的单例中,并从已启动的活动中访问它们。



实现每种方法的方式和原因的一些示例:



在意图内发送数据



  Intent intent = new Intent(FirstActivity.this,SecondActivity 。类); 
intent.putExtra(some_key,value);
intent.putExtra(some_other_key,一个值);
startActivity(intent);

第二项活动:

  Bundle bundle = getIntent()。getExtras(); 
int value = bundle.getInt(some_key);
String value2 = bundle.getString(some_other_key);

如果要传递原始数据或字符串,请使用此方法。您还可以传递实现 Serializable 的对象。



虽然很诱人,但在使用<$ c $之前应该三思而后行c> Serializable :它容易出错并且非常慢。所以一般来说:如果可能的话,远离 Serializable 。如果要传递复杂的用户定义对象,请查看 Parcelable 界面。实现起来比较困难,但与 Serializable 相比,它具有相当大的速度提升。



共享数据而不会持久化到磁盘



通过将活动保存在内存中,可以在活动之间共享数据,因为在大多数情况下,两个活动都在同一个进程中运行。



注意:有时,当用户离开您的活动时(不退出),Android可能会决定终止您的应用。在这种情况下,我遇到过这样的情况:android尝试使用在应用程序被杀之前提供的意图启动最后一个活动。在这种情况下,存储在单例(您的或应用程序)中的数据将会消失,并且可能会发生错误。为了避免这种情况,您可以将对象保存到磁盘或在使用它之前检查数据以确保其有效。



使用单例类



有一个类来保存数据:

  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;}
}

From已启动的活动:

  String data = DataHolder.getInstance()。getData(); 



使用应用程序单例



应用程序单例是应用程序启动时创建的 android.app.Application 的实例。您可以通过扩展应用程序来提供自定义的:

  import android。 app.Application; 
公共类MyApplication扩展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();



静态字段



这个想法基本上是与单例相同,但在这种情况下,您提供对数据的静态访问:

 公共类DataHolder {
私有静态字符串数据;
public static String getData(){return data;}
public static String setData(String data){DataHolder.data = data;}
}

从已启动的活动中:

 字符串数据= DataHolder.getData(); 



HashMap WeakReferences



同样的想法,但允许垃圾收集器删除未引用的对象(例如,当用户退出活动时):

 公共类DataHolder {
Map< String,WeakReference< Object>> data = new HashMap< String,WeakReference< Object>>();

void save(String id,Object object){
data.put(id,new WeakReference< Object>(object));
}

对象检索(String id){
WeakReference< Object> objectWeakReference = data.get(id);
返回objectWeakReference.get();
}
}

在启动活动之前:

  DataHolder.getInstance()。save(someId,someObject); 

从已启动的活动中:



<$ p $ 。p> DataHolder.getInstance()取回(someId);

您可能需要或不必使用intent的附加内容传递对象ID。这一切都取决于您的具体问题。



将对象持久保存到磁盘



想法是保存数据启动其他活动之前的磁盘。



优点:您可以从其他地方启动活动,如果数据已经保留,则应该工作得很好。



缺点:这很麻烦,需要更多时间来实施。需要更多代码,因此更有可能引入错误。它也会慢得多。



一些持久对象的方法包括:




I have one activity which is the main activity used throughout the app and it has a number of variables. I have two other activities which I would like to be able to use the data from the first activity. Now I know I can do something like this:

GlobalState gs = (GlobalState) getApplication();
String s = gs.getTestMe();

However I want to share a lot of variables and some might be rather large so I don't want to be creating copies of them like above.

Is there a way to directly get and change the variables without using get and set methods? I remember reading an article on the Google dev site saying this is not recommended for performance on Android.

解决方案

Here a compilation of most common ways to achieve this:

  • Send data inside intent
  • Static fields
  • HashMap of WeakReferences
  • Persist objects (sqlite, share preferences, file, etc.)

TL;DR: there are two ways of sharing data: passing data in the intent's extras or saving it somewhere else. If data is primitives, Strings or user-defined objects: send it as part of the intent extras (user-defined objects must implement Parcelable). If passing complex objects save an instance in a singleton somewhere else and access them from the launched activity.

Some examples of how and why to implement each approach:

Send data inside intents

Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("some_key", value);
intent.putExtra("some_other_key", "a value");
startActivity(intent);

On the second activity:

Bundle bundle = getIntent().getExtras();
int value = bundle.getInt("some_key");
String value2 = bundle.getString("some_other_key");

Use this method if you are passing primitive data or Strings. You can also pass objects that implements Serializable.

Although tempting, you should think twice before using Serializable: it's error prone and horribly slow. So in general: stay away from Serializable if possible. If you want to pass complex user-defined objects, take a look at the Parcelable interface. It's harder to implement, but it has considerable speed gains compared to Serializable.

Share data without persisting to disk

It is possible to share data between activities by saving it in memory given that, in most cases, both activities run in the same process.

Note: sometimes, when the user leaves your activity (without quitting it), Android may decide to kill your application. In such scenario, I have experienced cases in which android attempts to launch the last activity using the intent provided before the app was killed. In this cases, data stored in a singleton (either yours or Application) will be gone and bad things could happen. To avoid such cases, you either persist objects to disk or check data before using it to make sure its valid.

Use a singleton class

Have a class to hold the data:

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;}
}

From the launched activity:

String data = DataHolder.getInstance().getData();

Use application singleton

The application singleton is an instance of android.app.Application which is created when the app is launched. You can provide a custom one by extending 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;}
}

Before launching the activity:

MyApplication app = (MyApplication) getApplicationContext();
app.setData(someData);

Then, from the launched activity:

MyApplication app = (MyApplication) getApplicationContext();
String data = app.getData();

Static fields

The idea is basically the same as the singleton, but in this case you provide static access to the data:

public class DataHolder {
  private static String data;
  public static String getData() {return data;}
  public static String setData(String data) {DataHolder.data = data;}
}

From the launched activity:

String data = DataHolder.getData();

HashMap of WeakReferences

Same idea, but allowing the garbage collector to removed unreferenced objects (e.g. when the user quits the activity):

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();
  }
}

Before launching the activity:

DataHolder.getInstance().save(someId, someObject);

From the launched activity:

DataHolder.getInstance().retrieve(someId);

You may or may not have to pass the object id using the intent’s extras. It all depends on your specific problem.

Persist objects to disk

The idea is to save the data in disk before launching the other activity.

Advantages: you can launch the activity from other places and, if the data is already persisted, it should work just fine.

Disadvantages: it’s cumbersome and takes more time to implement. Requires more code and thus more chance of introducing bugs. It will also be much slower.

Some of the ways to persist objects include:

这篇关于在活动之间共享数据的最佳方式是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆