如何在Android应用程序中的活动之间传递数据?
我有一个场景,通过login页面login后,每个activity
都会有一个注销button
。
在点击登出时,我会传递login用户的session id
来注销。 任何人都可以指导我如何保持session id
可用于所有activities
?
任何替代这种情况
最简单的方法是将会话ID传递给您用来启动活动的意图的注销活动:
Intent intent = new Intent(getBaseContext(), SignoutActivity.class); intent.putExtra("EXTRA_SESSION_ID", sessionId); startActivity(intent);
访问下一个活动的意图
String s = getIntent().getStringExtra("EXTRA_SESSION_ID");
Intents的文档有更多的信息(请看“Extras”部分)。
在您当前的Activity中,创build一个新的Intent:
Intent i = new Intent(getApplicationContext(), NewActivity.class); i.putExtra("key","value"); startActivity(i);
然后在新的活动中,检索这些值:
Bundle extras = getIntent().getExtras(); if (extras != null) { String value = extras.getString("key"); //The key argument here must match that used in the other activity }
使用这种技术将variables从一个Activity传递到另一个。
Erich指出,传递意图额外是一个好方法。
Application对象是另外一种方式,当处理多个活动中的相同状态(而不是必须在/到处)或者比基元和string更复杂的对象时,它有时更容易。
您可以扩展应用程序,然后设置/获取您想要的任何内容,并使用getApplication()从任何Activity(在同一应用程序中)访问它。
另外请记住,您可能会看到的其他方法,如静态,可能会有问题,因为它们可能导致内存泄漏 。 应用程序也帮助解决这个
来源课程:
Intent myIntent = new Intent(this, NewActivity.class); myIntent.putExtra("firstName", "Your First Name Here"); myIntent.putExtra("lastName", "Your Last Name Here"); startActivity(myIntent)
目标类(NewActivity类):
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.view); Intent intent = getIntent(); String fName = intent.getStringExtra("firstName"); String lName = intent.getStringExtra("lastName"); }
你只需发送额外的东西,同时打电话给你的意图。
喜欢这个:
Intent intent = new Intent(getApplicationContext(), SecondActivity.class); intent.putExtra("Variable name", "Value you want to pass"); startActivity(intent);
现在你的SecondActivity
的OnCreate
方法,你可以像这样获取额外的东西。
如果你发送的价值long
:
long value = getIntent().getLongExtra("Variable name which you sent as an extra", defaultValue(you can give it anything));
如果您发送的值是一个String
:
String value = getIntent().getStringExtra("Variable name which you sent as an extra");
如果您发送的值是Boolean
:
Boolean value = getIntent().getBooleanExtra("Variable name which you sent as an extra", defaultValue);
更新请注意,我曾提到使用SharedPreference 。 它有一个简单的API,可以在应用程序的活动中访问。 但是,这是一个笨拙的解决scheme,如果您传递敏感数据,则会带来安全风险。 最好使用意图。 它有一个重载的方法的广泛的列表,可以用来更好地传输活动之间的许多不同的数据types。 看看intent.putExtra 。 这个链接很好地展示了putExtra的使用。
尝试执行以下操作:
创build一个简单的“助手”类(工厂为您的意图),如下所示:
import android.content.Intent; public class IntentHelper { public static final Intent createYourSpecialIntent(Intent src) { return new Intent("YourSpecialIntent").addCategory("YourSpecialCategory").putExtras(src); } }
这将是你所有意图的工厂。 每当你需要一个新的Intent,在IntentHelper中创build一个静态工厂方法。 要创build一个新的意图,你应该这样说:
IntentHelper.createYourSpecialIntent(getIntent());
在你的活动中。 当你想在“会话”中“保存”一些数据时,只需使用以下命令:
IntentHelper.createYourSpecialIntent(getIntent()).putExtra("YOUR_FIELD_NAME", fieldValueToSave);
并发送这个意图。 在目标活动中,您的字段将可用:
getIntent().getStringExtra("YOUR_FIELD_NAME");
所以现在我们可以像使用相同的旧会话一样使用Intent(就像在servlet或JSP中一样 )。
您也可以通过创build可分类的类来传递自定义类对象。 最好的方法是让你的课程写出来,然后把它粘贴到http://www.parcelabler.com/这样的网站上; 。 点击构build,你会得到新的代码。 复制所有这些,并replace原来的课程内容。 然后-
Intent intent = new Intent(getBaseContext(), NextActivity.class); Foo foo = new Foo(); intent.putExtra("foo", foo); startActivity(intent);
并在NextActivity中得到结果 –
Foo foo = getIntent().getExtras().getParcelable("foo");
现在,您可以简单地使用foo对象,就像您使用的那样。
另一种方法是使用存储数据的公共静态字段,即:
public class MyActivity extends Activity { public static String SharedString; public static SomeObject SharedObject; //...
标准的方法。
Intent i = new Intent(this, ActivityTwo.class); AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.autocomplete); String getrec=textView.getText().toString(); Bundle bundle = new Bundle(); bundle.putString(“stuff”, getrec); i.putExtras(bundle); startActivity(i);
现在在第二个活动中从包中检索数据:
获得捆绑
Bundle bundle = getIntent().getExtras();
提取数据…
String stuff = bundle.getString(“stuff”);
在活动之间传递数据最方便的方式是传递意图。 在您想要发送数据的第一个活动中,您应该添加代码,
String str = "My Data"; //Data you want to send Intent intent = new Intent(FirstActivity.this, SecondActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra("name",str); //Here you will add the data into intent to pass bw activites v.getContext().startActivity(intent);
你也应该导入
import android.content.Intent;
然后在下一个Acitvity(SecondActivity)中,您应该使用以下代码从意图中检索数据。
String name = this.getIntent().getStringExtra("name");
你可以使用SharedPreferences
…
-
日志logging。 在
SharedPreferences
存储会话IDSharedPreferences preferences = getSharedPreferences("session",getApplicationContext().MODE_PRIVATE); Editor editor = preferences.edit(); editor.putString("sessionId", sessionId); editor.commit();
-
登出。 在sharedpreferences中获取会话ID
SharedPreferences preferences = getSharedPreferences("session", getApplicationContext().MODE_PRIVATE); String sessionId = preferences.getString("sessionId", null);
如果您没有所需的会话ID,请删除sharedpreferences:
SharedPreferences settings = context.getSharedPreferences("session", Context.MODE_PRIVATE); settings.edit().clear().commit();
这是非常有用的,因为有一次你保存的价值,然后检索活动的任何地方。
这有助于我在上下文中看到事物。 这里有两个例子。
通过数据前进
主要活动
- 将您想要发送的数据与键值对配合使用。 看到这个答案命名约定的关键。
- 用
startActivity
开始第二个活动。
MainActivity.java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } // "Go to Second Activity" button click public void onButtonClick(View view) { // get the text to pass EditText editText = (EditText) findViewById(R.id.editText); String textToPass = editText.getText().toString(); // start the SecondActivity Intent intent = new Intent(this, SecondActivity.class); intent.putExtra(Intent.EXTRA_TEXT, textToPass); startActivity(intent); } }
第二个活动
- 您使用
getIntent()
来获取启动第二个活动的Intent
。 然后,您可以使用getExtras()
和您在第一个活动中定义的键提取数据。 由于我们的数据是一个string,我们将在这里使用getStringExtra
。
SecondActivity.java
public class SecondActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); // get the text from MainActivity Intent intent = getIntent(); String text = intent.getStringExtra(Intent.EXTRA_TEXT); // use the text in a TextView TextView textView = (TextView) findViewById(R.id.textView); textView.setText(text); } }
通过数据返回
主要活动
- 用
startActivityForResult
启动第二个活动,提供一个任意的结果代码。 - 覆盖
onActivityResult
。 这在第二个活动结束时被调用。 您可以通过检查结果代码确保它实际上是第二个活动。 (当您从同一主要活动开始多个不同的活动时,这非常有用。) - 提取您从返回
Intent
获得的数据。 数据是使用键值对提取的。 我可以使用任何string的关键,但我会使用预定义的Intent.EXTRA_TEXT
因为我发送文本。
MainActivity.java
public class MainActivity extends AppCompatActivity { private static final int SECOND_ACTIVITY_RESULT_CODE = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } // "Go to Second Activity" button click public void onButtonClick(View view) { // Start the SecondActivity Intent intent = new Intent(this, SecondActivity.class); startActivityForResult(intent, SECOND_ACTIVITY_RESULT_CODE); } // This method is called when the second activity finishes @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // check that it is the SecondActivity with an OK result if (requestCode == SECOND_ACTIVITY_RESULT_CODE) { if (resultCode == RESULT_OK) { // get String data from Intent String returnString = data.getStringExtra(Intent.EXTRA_TEXT); // set text view with string TextView textView = (TextView) findViewById(R.id.textView); textView.setText(returnString); } } } }
第二个活动
- 将您想要发送回前一个活动的数据放入一个
Intent
。 数据使用键值对存储在Intent
。 我select为我的密钥使用Intent.EXTRA_TEXT
。 - 将结果设置为
RESULT_OK
并添加保存数据的意图。 - 调用
finish()
closures第二个Activity。
SecondActivity.java
public class SecondActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); } // "Send text back" button click public void onButtonClick(View view) { // get the text from the EditText EditText editText = (EditText) findViewById(R.id.editText); String stringToPassBack = editText.getText().toString(); // put the String to pass back into an Intent and close this activity Intent intent = new Intent(); intent.putExtra(Intent.EXTRA_TEXT, stringToPassBack); setResult(RESULT_OK, intent); finish(); } }
从活动
int n= 10; Intent in = new Intent(From_Activity.this,To_Activity.class); Bundle b1 = new Bundle(); b1.putInt("integerNumber",n); in.putExtras(b1); startActivity(in);
活动
Bundle b2 = getIntent().getExtras(); int m = 0; if(b2 != null) { m = b2.getInt("integerNumber"); }
您可以使用意向对象在活动之间发送数据。 考虑你有两个活动,即FirstActivity
和SecondActivity
。
FirstActivity内部:
使用意图:
i = new Intent(FirstActivity.this,SecondActivity.class); i.putExtra("key", value); startActivity(i)
里面SecondActivity
Bundle bundle= getIntent().getExtras();
现在,您可以使用不同的bundle类方法来获取由FirstActivity按键传递的值。
例如, bundle.getString("key")
, bundle.getDouble("key")
, bundle.getInt("key")
等
如果你想在Activites / Fragments之间传输位图
活动
在Activites之间传递一个位图
Intent intent = new Intent(this, Activity.class); intent.putExtra("bitmap", bitmap);
并在Activity类中
Bitmap bitmap = getIntent().getParcelableExtra("bitmap");
分段
在碎片之间传递一个位图
SecondFragment fragment = new SecondFragment(); Bundle bundle = new Bundle(); bundle.putParcelable("bitmap", bitmap); fragment.setArguments(bundle);
在SecondFragment里面接收
Bitmap bitmap = getArguments().getParcelable("bitmap");
传输大的位图
如果您的绑定事务处理失败,则意味着您将大元素从一个活动转移到另一个活动,从而超出了绑定事务缓冲区。
所以在这种情况下,您必须将位图压缩为一个字节的数组,然后在另一个活动中解压缩 ,如下所示
在FirstActivity
Intent intent = new Intent(this, SecondActivity.class); ByteArrayOutputStream stream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPG, 100, stream); byte[] bytes = stream.toByteArray(); intent.putExtra("bitmapbytes",bytes);
而在第二活动
byte[] bytes = getIntent().getByteArrayExtra("bitmapbytes"); Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Intent intent = new Intent(YourCurrentActivity.this, YourActivityName.class); intent.putExtra("NAme","John"); intent.putExtra("Id",1); startActivity(intent);
您可以在其他活动中检索它。 两种方式:
int id = getIntent.getIntExtra("id", /* defaltvalue */ 2);
第二种方法是:
Intent i = getIntent(); String name = i.getStringExtra("name");
活动之间的数据传递主要是通过一个意图对象来实现的。
首先,您必须使用Bundle
类将数据附加到intent对象。 然后使用startActivity()
或startActivityForResult()
方法调用该活动。
你可以find更多关于它的信息,例如博客文章将数据传递给活动 。
您可以尝试共享首选项,这可能是在活动之间共享数据的好select
保存会话ID –
SharedPreferences pref = myContexy.getSharedPreferences("Session Data",MODE_PRIVATE); SharedPreferences.Editor edit = pref.edit(); edit.putInt("Session ID", session_id); edit.commit();
为了得到他们 –
SharedPreferences pref = myContexy.getSharedPreferences("Session Data", MODE_PRIVATE); session_id = pref.getInt("Session ID", 0);
/* * If you are from transferring data from one class that doesn't * extend Activity, then you need to do something like this. */ public class abc { Context context; public abc(Context context) { this.context = context; } public void something() { context.startactivity(new Intent(context, anyone.class).putextra("key", value)); } }
我在一个类中使用静态字段,并获取/设置它们:
喜欢:
public class Info { public static int ID = 0; public static String NAME = "TEST"; }
为了获得一个值,在一个Activity中使用它:
Info.ID Info.NAME
设置一个值:
Info.ID = 5; Info.NAME = "USER!";
补充答案:密钥string的命名约定
传递数据的实际过程已经被回答,但是大多数答案在意图中使用硬编码的string作为键名。 只有在您的应用程序中使用这通常很好。 但是, 文档build议使用EXTRA_*
常量来标准化数据types。
示例1:使用Intent.EXTRA_*
键
第一个活动
Intent intent = new Intent(getActivity(), SecondActivity.class); intent.putExtra(Intent.EXTRA_TEXT, "my text"); startActivity(intent);
第二项活动:
Intent intent = getIntent(); String myText = intent.getExtras().getString(Intent.EXTRA_TEXT);
示例2:定义您自己的static final
密钥
如果其中一个Intent.EXTRA_*
string不适合您的需求,您可以在第一个活动开始时定义自己的。
static final String EXTRA_STUFF = "com.myPackageName.EXTRA_STUFF";
如果您只在自己的应用程序中使用密钥,那么包名仅仅是一个约定。 但是,如果您正在创build其他应用可以使用Intent调用的某种服务,则必须避免命名冲突。
第一次活动:
Intent intent = new Intent(getActivity(), SecondActivity.class); intent.putExtra(EXTRA_STUFF, "my text"); startActivity(intent);
第二项活动:
Intent intent = getIntent(); String myText = intent.getExtras().getString(FirstActivity.EXTRA_STUFF);
示例3:使用string资源键
虽然在文档中没有提到,但这个答案build议使用一个string资源来避免活动之间的依赖关系。
strings.xml中
<string name="EXTRA_STUFF">com.myPackageName.MY_NAME</string>
第一个活动
Intent intent = new Intent(getActivity(), SecondActivity.class); intent.putExtra(getString(R.string.EXTRA_STUFF), "my text"); startActivity(intent);
第二个活动
Intent intent = getIntent(); String myText = intent.getExtras().getString(getString(R.string.EXTRA_STUFF));
尝试这个:
CurrentActivity.java
Intent intent = new Intent(currentActivity.this, TargetActivity.class); intent.putExtra("booktype", "favourate"); startActivity(intent);
TargetActivity.java
Bundle b = getIntent().getExtras(); String typesofbook = b.getString("booktype");
这是我的最佳实践,当这个项目非常庞大而且复杂的时候,它会有很大帮助。
假设我有2个活动, SplashActivity
和HomeActivity
。 我想从SplashActivity
传递2个参数(用户名和密码)到HomeActivity
。
首先,我创build我的HomeIntent
public class HomeIntent extends Intent { private static final String ACTION_LOGIN = "action_login"; private static final String ACTION_LOGOUT = "action_logout"; private static final String ARG_USERNAME = "arg_username"; private static final String ARG_PASSWORD = "arg_password"; public HomeIntent(Context ctx, boolean isLogIn) { this(ctx); //set action type setAction(isLogIn ? ACTION_LOGIN : ACTION_LOGOUT); } public HomeIntent(Context ctx) { super(ctx, HomeActivity.class); } //This will be needed for receiving data public HomeIntent(Intent intent) { super(intent); } public void setData(String userName, String password) { putExtra(ARG_USERNAME, userName); putExtra(ARG_PASSWORD, password); } public String getUsername() { return getStringExtra(ARG_USERNAME); } public String getPassword() { return getStringExtra(ARG_PASSWORD); } //To separate the params is for which action, we should create action public boolean isActionLogIn() { return getAction().equals(ACTION_LOGIN); } public boolean isActionLogOut() { return getAction().equals(ACTION_LOGOUT); } }
以下是我如何在SplashActivity中传递数据
public class SplashActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); String username = "phearum"; String password = "pwd1133"; final boolean isActionLogin = true; //Passing data to HomeActivity final HomeIntent homeIntent = new HomeIntent(this, isActionLogin); homeIntent.setData(username, password); startActivity(homeIntent); } }
最后一步,这里是我如何在HomeActivity
接收数据
public class HomeActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); //This is how we receive the data from SplashActivity //Make sure you pass getIntent() to the HomeIntent constructor final HomeIntent homeIntent = new HomeIntent(getIntent()); Log.d("HomeActivity", "Is action login? " + homeIntent.isActionLogIn()); Log.d("HomeActivity", "username: " + homeIntent.getUsername()); Log.d("HomeActivity", "password: " + homeIntent.getPassword()); } }
完成! 酷:)我只是想分享我的经验。 如果你在小项目上工作,这不应该是大问题。 但是当你在大项目上工作的时候,当你想重构或修复错误的时候真的很痛苦。
我最近发布了VAPI API ,这是一个jQuery风格的Android框架,可以让所有类似的任务变得更简单。 如前所述, SharedPreferences
是您可以执行此操作的一种方法。
VaporSharedPreferences
是作为Singleton实现的,所以这是一种select,在.put(...)
API中它有一个重载的.put(...)
方法,所以你不必明确地担心你提交的数据types – 提供它是受支持的。 这也是stream利的,所以你可以连锁电话:
$.prefs(...).put("val1", 123).put("val2", "Hello World!").put("something", 3.34);
它还可以自动保存更改,并统一读写过程,所以不需要像在标准Android中那样显式检索编辑器。
或者你可以使用Intent
。 在Vapor API中,你也可以在.put(...)
使用可.put(...)
重载的.put(...)
方法:
$.Intent().put("data", "myData").put("more", 568)...
并作为一个额外的传递,如其他答案中所述。 你可以从你的Activity
检索额外的,而且如果你使用VaporActivity
这是为你自动完成的,所以你可以使用:
this.extras()
在您切换到的Activity
的另一端检索它们。
希望有兴趣的一些:)
使用全球课程:
public class GlobalClass extends Application { private float vitamin_a; public float getVitaminA() { return vitamin_a; } public void setVitaminA(float vitamin_a) { this.vitamin_a = vitamin_a; } }
你可以从所有其他类中调用这个类的setters和getters。 这样做,你需要在每个实体中创build一个GlobalClass对象:
GlobalClass gc = (GlobalClass) getApplication();
那么你可以打电话举例说明:
gc.getVitaminA()
Charlie Collins使用Application类给了我一个完美的答案。 我不知道我们可以很容易地进行子类化。 这是使用自定义应用程序类的简化示例。
AndroidManifest.xml中
给android:name
属性使用你自己的应用程序类。
... <application android:name="MyApplication" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > ....
MyApplication.java
将其用作全球参考持有者。 它在同一个过程中工作正常。
public class MyApplication extends Application { private MainActivity mainActivity; @Override public void onCreate() { super.onCreate(); } public void setMainActivity(MainActivity activity) { this.mainActivity=activity; } public MainActivity getMainActivity() { return mainActivity; } }
MainActivity.java
将全局“单例”引用设置为应用程序实例。
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((MyApplication)getApplication()).setMainActivity(this); } ... }
MyPreferences.java
一个简单的例子,我使用另一个活动实例的主要活动。
public class MyPreferences extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener { @SuppressWarnings("deprecation") @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); PreferenceManager.getDefaultSharedPreferences(this) .registerOnSharedPreferenceChangeListener(this); } @Override public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { if (!key.equals("autostart")) { ((MyApplication)getApplication()).getMainActivity().refreshUI(); } } }
活动之间有多种方式传递数据, 文档中有很多方法。
对于大多数情况下,Intent.putExtras就足够了。
你可以使用意图
Intent mIntent = new Intent(FirstActivity.this, SecondActivity.class); mIntent.putExtra("data", data); startActivity(mIntent);
另一种可以使用单例模式的方法也是:
public class DataHolder { private static DataHolder dataHolder; private List<Model> dataList; public void setDataList(List<Model>dataList) { this.dataList = dataList; } public List<Model> getDataList() { return dataList; } public synchronized static DataHolder getInstance() { if (dataHolder == null) { dataHolder = new DataHolder(); } return dataHolder; }
}
从你的FirstActivity
private List<Model> dataList = new ArrayList<>(); DataHolder.getInstance().setDataList(dataList);
关于SecondActivity
private List<Model> dataList = DataHolder.getInstance().getDataList();
我使用公共静态字段来存储活动之间的共享数据,但为了尽量减less其副作用,您可以:
- 只做一个字段,或尽可能less的字段,并重新使用它们,使它们成为types对象,并在接收活动中将其转换为所需的types。
- 每当它们中的任何一个都不再有用时,将其显式设置为null,以便在下一次分配之前由垃圾收集器收集。
- android从文件path中绘制
- hex透明度的颜色
- AsyncTask和Android上的error handling
- java.lang.IllegalStateException:在onSaveInstanceState后无法执行此操作
- 理解onTrimMemory(int level)
- 在使用基于Gradle的configuration时,在Android Studio(IntelliJ)上运行简单的JUnittesting
- Android – ListView – performItemClick
- 如何捕捉VideoView的“对不起,这个video不能播放”错误
- 自定义可绘制ProgressBar / ProgressDialog