如何在Android应用程序中的活动之间传递数据?

How do I pass data between Activities in Android application?

我有一个场景,通过登录页面登录后,每个activity上都会有一个签出button

单击sign-out时,我将传递已登录用户的session id以注销。有人能指导我如何使所有的activities都能使用session id

除了这个案子还有别的办法吗


在您当前的活动中,创建一个新的Intent

1
2
3
4
String value="Hello world";
Intent i = new Intent(CurrentActivity.this, NewActivity.class);    
i.putExtra("key",value);
startActivity(i);

然后在新活动中,检索这些值:

1
2
3
4
5
Bundle extras = getIntent().getExtras();
if (extras != null) {
    String value = extras.getString("key");
    //The key argument here must match that used in the other activity
}

使用此技术将变量从一个活动传递到另一个活动。


最简单的方法是将会话ID传递给您用于启动活动的Intent中的签出活动:

1
2
3
Intent intent = new Intent(getBaseContext(), SignoutActivity.class);
intent.putExtra("EXTRA_SESSION_ID", sessionId);
startActivity(intent);

进入下一个活动的意图

1
String sessionId= getIntent().getStringExtra("EXTRA_SESSION_ID");

意向书文档有更多信息(请参阅标题为"附加内容"的部分)。


正如埃里希所指出的,通过意向附加条款是一种很好的方法。

然而,应用程序对象是另一种方式,有时在多个活动中处理相同的状态(而不是在任何地方都必须获取/放置它)或比基元和字符串更复杂的对象时更容易。

您可以扩展应用程序,然后在那里设置/获取您想要的任何内容,并使用getApplication()从任何活动(在同一应用程序中)访问它。

还要记住,您可能看到的其他方法(如静态方法)可能有问题,因为它们可能导致内存泄漏。应用程序也有助于解决这个问题。


源类:

1
2
3
4
Intent myIntent = new Intent(this, NewActivity.class);
myIntent.putExtra("firstName","Your First Name Here");
myIntent.putExtra("lastName","Your Last Name Here");
startActivity(myIntent)

目标类(NewActivity类):

1
2
3
4
5
6
7
8
9
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");
}


你只要在呼唤你的意图的时候发送额外的信息。

这样地:

1
2
3
Intent intent = new Intent(getApplicationContext(), SecondActivity.class);
intent.putExtra("Variable name","Value you want to pass");
startActivity(intent);

现在,在你的SecondActivityOnCreate方法中,你可以这样提取额外的东西。

如果您发送的值在long中:

1
long value = getIntent().getLongExtra("Variable name which you sent as an extra", defaultValue(you can give it anything));

如果您发送的值是一个String

1
String value = getIntent().getStringExtra("Variable name which you sent as an extra");

如果您发送的值是一个Boolean

1
Boolean value = getIntent().getBooleanExtra("Variable name which you sent as an extra", defaultValue);


更新说明,我提到了sharedreference的用法。它有一个简单的API,可以跨应用程序的活动进行访问。但这是一个笨拙的解决方案,如果您传递敏感数据,这将是一个安全风险。最好使用意图。它有大量的重载方法列表,可以用来更好地在活动之间传输许多不同的数据类型。看看intent.putextra。这个链接很好地展示了PutExtra的使用。

在活动之间传递数据时,我的首选方法是为相关活动创建一个静态方法,其中包括启动意图所需的参数。这样就可以方便地设置和检索参数。所以看起来像这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyActivity extends Activity {
    public static final String ARG_PARAM1 ="arg_param1";
...
public static getIntent(Activity from, String param1, Long param2...) {
    Intent intent = new Intent(from, MyActivity.class);
        intent.putExtra(ARG_PARAM1, param1);
        intent.putExtra(ARG_PARAM2, param2);
        return intent;
}

....
// Use it like this.
startActivity(MyActvitiy.getIntent(FromActivity.this, varA, varB, ...));
...

然后,您可以为预期的活动创建一个意图,并确保您拥有所有参数。你可以适应片段。上面有一个简单的例子,但是你明白了。


它有助于我从上下文中看到事物。这里有两个例子。

向前传递数据

enter image description here

主要活动

  • 将要发送的数据与键值对放在一起。有关键的命名约定,请参见此答案。
  • 使用startActivity启动第二个活动。

mainactivity.java(主活动.java)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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()和在第一个活动中定义的键提取数据。因为我们的数据是一个字符串,所以我们在这里只使用getStringExtra

第二活动.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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);
    }
}

返回数据

enter image description here

主要活动

  • startActivityForResult启动第二个活动,提供一个任意的结果代码。
  • 覆盖onActivityResult。当第二个活动结束时调用。通过检查结果代码,可以确保它实际上是第二个活动。(当您从同一个主活动开始多个不同的活动时,这很有用。)
  • 从返回的Intent中提取数据。使用键值对提取数据。我可以使用任何字符串作为键,但我将使用预定义的Intent.EXTRA_TEXT,因为我正在发送文本。

mainactivity.java(主活动.java)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class MainActivity extends AppCompatActivity {

    private static final int SECOND_ACTIVITY_REQUEST_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_REQUEST_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_REQUEST_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中。我选择用Intent.EXTRA_TEXT作为我的钥匙。
  • 将结果设置为RESULT_OK,并添加保存数据的意图。
  • 致电finish()关闭第二个活动。

第二活动.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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();
    }
}


尝试执行以下操作:

创建一个简单的"helper"类(出于您的目的而创建工厂),如下所示:

1
2
3
4
5
6
7
import android.content.Intent;

public class IntentHelper {
    public static final Intent createYourSpecialIntent(Intent src) {
          return new Intent("YourSpecialIntent").addCategory("YourSpecialCategory").putExtras(src);
    }
}

这将是你所有意图的工厂。每当你需要一个新的意图时,在intenthelper中创建一个静态工厂方法。要创建一个新的意图,您应该这样说:

1
IntentHelper.createYourSpecialIntent(getIntent());

在你的活动中。当您想在"会话"中"保存"一些数据时,只需使用以下命令:

1
IntentHelper.createYourSpecialIntent(getIntent()).putExtra("YOUR_FIELD_NAME", fieldValueToSave);

并传达这个意图。在目标活动中,您的字段可用为:

1
getIntent().getStringExtra("YOUR_FIELD_NAME");

所以现在我们可以像使用相同的旧会话一样使用意图(比如servlet或jsp)。


您还可以通过创建Parcelable类来传递自定义类对象。使其成为Parcelable的最佳方法是编写类,然后简单地将其粘贴到http://www.parcelabler.com/这样的站点。单击build,您将获得新代码。复制所有这些内容并替换原始类内容。然后——

1
2
3
4
Intent intent = new Intent(getBaseContext(), NextActivity.class);
Foo foo = new Foo();
intent.putExtra("foo", foo);
startActivity(intent);

得到下触觉的结果-

1
Foo foo = getIntent().getExtras().getParcelable("foo");

现在您可以像使用一样简单地使用foo对象。


另一种方法是使用存储数据的公共静态字段,即:

1
2
3
4
5
6
public class MyActivity extends Activity {

  public static String SharedString;
  public static SomeObject SharedObject;

//...


在活动之间传递数据最方便的方法是传递意图。在要从中发送数据的第一个活动中,应添加代码,

1
2
3
4
5
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);

您还应该导入

1
import android.content.Intent;

然后在下一个acitvity(secondactivity)中,您应该使用以下代码从意图中检索数据。

1
String name = this.getIntent().getStringExtra("name");


你可以用SharedPreferences

  • 登录中。SharedPreferences中的时间存储会话ID

    1
    2
    3
    4
    SharedPreferences preferences = getSharedPreferences("session",getApplicationContext().MODE_PRIVATE);
    Editor editor = preferences.edit();
    editor.putString("sessionId", sessionId);
    editor.commit();
  • Signout。sharedPreferences中的时间获取会话ID

    1
    2
    SharedPreferences preferences = getSharedPreferences("session", getApplicationContext().MODE_PRIVATE);
    String sessionId = preferences.getString("sessionId", null);
  • 如果没有所需的会话ID,请删除sharedreferences:

    1
    2
    SharedPreferences settings = context.getSharedPreferences("session", Context.MODE_PRIVATE);
    settings.edit().clear().commit();

    这非常有用,因为有一次您保存了值,然后在活动的任何地方检索。


    标准方法。

    1
    2
    3
    4
    5
    6
    7
    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);

    现在,在第二个活动中,从包中检索数据:

    得到捆

    1
    Bundle bundle = getIntent().getExtras();

    提取数据…

    1
    String stuff = bundle.getString("stuff");


    从活动

    1
    2
    3
    4
    5
    6
     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);

    对活动

    1
    2
    3
    4
    5
    6
     Bundle b2 = getIntent().getExtras();
     int m = 0;
     if(b2 != null)
      {
         m = b2.getInt("integerNumber");
      }


    您可以使用意向对象在活动之间发送数据。假设您有两个活动,即FirstActivitySecondActivity

    在FirstActivity中:

    使用意图:

    1
    2
    3
    i = new Intent(FirstActivity.this,SecondActivity.class);
    i.putExtra("key", value);
    startActivity(i)

    在第二个活动中

    1
    Bundle bundle= getIntent().getExtras();

    现在,您可以使用不同的bundle类方法来获取从firstactivity按键传递的值。

    例如。bundle.getString("key")bundle.getDouble("key")bundle.getInt("key")等。


    如果要在活动/片段之间传输位图

    活动

    在活动之间传递位图

    1
    2
    Intent intent = new Intent(this, Activity.class);
    intent.putExtra("bitmap", bitmap);

    在活动课上

    1
    Bitmap bitmap = getIntent().getParcelableExtra("bitmap");

    破片

    在片段之间传递位图

    1
    2
    3
    4
    SecondFragment fragment = new SecondFragment();
    Bundle bundle = new Bundle();
    bundle.putParcelable("bitmap", bitmap);
    fragment.setArguments(bundle);

    在第二个片段中接收

    1
    Bitmap bitmap = getArguments().getParcelable("bitmap");

    传输大位图

    如果绑定器事务失败,这意味着您正在通过将大元素从一个活动传输到另一个活动来超过绑定器事务缓冲区。

    因此,在这种情况下,您必须将位图压缩为一个字节数组,然后在另一个活动中解压缩它,如下所示

    在第一个活动中

    1
    2
    3
    4
    5
    6
    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);

    在第二个活动中

    1
    2
    byte[] bytes = getIntent().getByteArrayExtra("bitmapbytes");
    Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);

    1
    2
    3
    4
    Intent intent = new Intent(YourCurrentActivity.this, YourActivityName.class);
    intent.putExtra("NAme","John");
    intent.putExtra("Id",1);
    startActivity(intent);

    您可以在另一个活动中检索它。两种方式:

    1
    int id = getIntent.getIntExtra("id", /* defaltvalue */ 2);

    第二种方法是:

    1
    2
    Intent i = getIntent();
    String name = i.getStringExtra("name");


    这是我的最佳实践,当项目巨大且复杂时,它会有很大帮助。

    假设我有两个活动,LoginActivityHomeActivity。我想将2个参数(用户名和密码)从LoginActivity传递到HomeActivity

    首先,我创建了我的HomeIntent

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    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);
        }
    }

    以下是我在逻辑活动中传递数据的方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class LoginActivity extends AppCompatActivity {
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_login);

            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中的数据。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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 LoginActivity
            //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());
        }
    }

    完成!酷:)我只想分享我的经历。如果你在小项目上工作,这不应该是大问题。但是当你在大项目上工作时,当你想重构或者修复bug的时候,你会非常痛苦。


    活动之间的数据传递主要是通过意向对象来实现的。

    首先,您必须使用Bundle类将数据附加到意向对象。然后使用startActivity()startActivityForResult()方法调用活动。

    你可以找到更多关于它的信息,比如从博客文章中向一个活动传递数据。


    您可以尝试共享首选项,这可能是在活动之间共享数据的一个很好的替代方法。

    保存会话ID-

    1
    2
    3
    4
    5
    SharedPreferences pref = myContexy.getSharedPreferences("Session
    Data",MODE_PRIVATE);
    SharedPreferences.Editor edit = pref.edit();
    edit.putInt("Session ID", session_id);
    edit.commit();

    得到它们

    1
    2
    SharedPreferences pref = myContexy.getSharedPreferences("Session Data", MODE_PRIVATE);
    session_id = pref.getInt("Session ID", 0);


    补充答案:键字符串的命名约定

    传递数据的实际过程已经被应答,但是大多数应答都使用硬编码字符串作为目的中的密钥名。只有在应用程序中使用时,这通常很好。但是,文档建议将EXTRA_*常量用于标准化数据类型。

    示例1:使用Intent.EXTRA_*

    第一活动

    1
    2
    3
    Intent intent = new Intent(getActivity(), SecondActivity.class);
    intent.putExtra(Intent.EXTRA_TEXT,"my text");
    startActivity(intent);

    第二项活动:

    1
    2
    Intent intent = getIntent();
    String myText = intent.getExtras().getString(Intent.EXTRA_TEXT);

    示例2:定义自己的static final

    如果某个Intent.EXTRA_*字符串不适合您的需要,您可以在第一个活动开始时定义自己的字符串。

    1
    static final String EXTRA_STUFF ="com.myPackageName.EXTRA_STUFF";

    如果您只在自己的应用程序中使用密钥,那么包含包名称只是一种约定。但是,如果您正在创建其他应用程序可以有意调用的某种服务,则必须避免命名冲突。

    第一项活动:

    1
    2
    3
    Intent intent = new Intent(getActivity(), SecondActivity.class);
    intent.putExtra(EXTRA_STUFF,"my text");
    startActivity(intent);

    第二项活动:

    1
    2
    Intent intent = getIntent();
    String myText = intent.getExtras().getString(FirstActivity.EXTRA_STUFF);

    示例3:使用字符串资源键

    尽管文档中没有提到,但此答案建议使用字符串资源来避免活动之间的依赖关系。

    StrugsXML

    1
     <string name="EXTRA_STUFF">com.myPackageName.MY_NAME</string>

    第一活动

    1
    2
    3
    Intent intent = new Intent(getActivity(), SecondActivity.class);
    intent.putExtra(getString(R.string.EXTRA_STUFF),"my text");
    startActivity(intent);

    第二活动

    1
    2
    Intent intent = getIntent();
    String myText = intent.getExtras().getString(getString(R.string.EXTRA_STUFF));

    从此活动启动另一个活动通过bundle对象传递参数

    1
    2
    3
    Intent intent = new Intent(getBaseContext(), YourActivity.class);
    intent.putExtra("USER_NAME","[email protected]");
    startActivity(intent);

    检索另一个活动(您的实际活动)

    1
    String s = getIntent().getStringExtra("USER_NAME");

    这对于简单类型的数据类型是可以的。但是如果你想在活动之间传递复杂的数据,你需要先将其序列化。

    这里有员工模型

    1
    2
    3
    4
    5
    6
    7
    8
    class Employee{
        private String empId;
        private int age;
        print Double salary;

        getters...
        setters...
    }

    您可以使用google提供的gson lib来序列化复杂的数据。这样地

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    String strEmp = new Gson().toJson(emp);
    Intent intent = new Intent(getBaseContext(), YourActivity.class);
    intent.putExtra("EMP", strEmp);
    startActivity(intent);

    Bundle bundle = getIntent().getExtras();
    String empStr = bundle.getString("EMP");
                Gson gson = new Gson();
                Type type = new TypeToken<Employee>() {
                }.getType();
                Employee selectedEmp = gson.fromJson(empStr, type);

    您可以使用Intent

    1
    2
    3
    Intent mIntent = new Intent(FirstActivity.this, SecondActivity.class);
    mIntent.putExtra("data", data);
    startActivity(mIntent);

    另一种方法也可以使用单例模式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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;
     }
    }

    从你的第一次活动开始

    1
    2
    private List<Model> dataList = new ArrayList<>();
    DataHolder.getInstance().setDataList(dataList);

    第二次活动

    1
    private List<Model> dataList = DataHolder.getInstance().getDataList();


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    /*
     * 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));
        }
    }


    我在类中使用静态字段,并获取/设置它们:

    像:

    1
    2
    3
    4
    5
    public class Info
    {
        public static int ID      = 0;
        public static String NAME ="TEST";
    }

    要获取值,请在活动中使用此选项:

    1
    2
    Info.ID
    Info.NAME

    设置值:

    1
    2
    Info.ID = 5;
    Info.NAME ="USER!";


    查理·柯林斯用Application.class给了我一个完美的答案。我不知道我们可以这么容易地将其分为子类。下面是一个使用自定义应用程序类的简化示例。

    AndroidManifest.xml

    android:name属性使用您自己的应用程序类。

    1
    2
    3
    4
    5
    6
    7
    ...
    <application android:name="MyApplication"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
    ....

    MyApplication.java

    将其用作全局参考持有者。它在同一个过程中运行良好。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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

    设置对应用程序实例的全局"singleton"引用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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

    使用另一个活动实例中的主活动的简单示例。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    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();
            }
        }
    }

    科特林

    从第一个活动传递

    1
    2
    3
    val intent = Intent(this, SecondActivity::class.java)
    intent.putExtra("key","value")
    startActivity(intent)

    进入第二个活动

    1
    val value = getIntent().getStringExtra("key")

    建议

    始终将密钥放在常量文件中以获得更有效的管理方式。

    1
    2
    3
    companion object {
        val KEY ="key"
    }

    试试这个:

    当前活动.java

    1
    2
    3
    Intent intent = new Intent(currentActivity.this, TargetActivity.class);
    intent.putExtra("booktype","favourate");
    startActivity(intent);

    目标活动.java

    1
    2
    Bundle b = getIntent().getExtras();
    String typesofbook = b.getString("booktype");


    我最近发布了vapor api,一个jquery风格的android框架,它可以简化类似这样的各种任务。如前所述,SharedPreferences是一种可以做到这一点的方法。

    VaporSharedPreferences是作为singleton实现的,因此这是一个选项,在vapor api中,它有一个重载的.put(...)方法,因此,只要支持它,就不必显式地担心正在提交的数据类型。它也很流畅,因此您可以连锁反应:

    1
    $.prefs(...).put("val1", 123).put("val2","Hello World!").put("something", 3.34);

    它还可以选择自动保存更改,并统一引擎盖下的读写过程,这样您就不需要像在标准Android中那样显式地检索编辑器。

    或者,您可以使用Intent。在vapor api中,也可以在VaporIntent上使用可链接的重载.put(...)方法:

    1
    $.Intent().put("data","myData").put("more", 568)...

    如其他答案中所述,将其作为额外部分传递。您可以从您的Activity中检索额外的内容,此外,如果您正在使用VaporActivity,这将自动为您完成,因此您可以使用:

    1
    this.extras()

    要在Activity的另一端检索它们,请切换到。

    希望这是一些人感兴趣的:)


    第一项活动:

    1
    2
    3
    Intent intent = new Intent(getApplicationContext(), ClassName.class);
    intent.putExtra("Variable name","Value you want to pass");
    startActivity(intent);

    第二项活动:

    1
    String str= getIntent().getStringExtra("Variable name which you sent as an extra");

    你可以通过意图在两个活动之间进行交流。每当您通过登录活动导航到任何其他活动时,您可以将sessionid设置为intent,并通过get intent()在其他活动中获取它。下面是它的代码段:

    LoginActivity:

    1
    2
    3
    4
    5
    Intent intent = new
    Intent(YourLoginActivity.this,OtherActivity.class);
    intent.putExtra("SESSION_ID",sessionId);
    startActivity(intent);
    finishAfterTransition();

    OtherActivity:

    In onCreate() or wherever you need it call
    getIntent().getStringExtra("SESSION_ID");
    Also make sure to check for if the intent is null and key you are passing in the intent should be same in both activities. Here is the
    full code snippet:

    1
    2
    3
            if(getIntent!=null && getIntent.getStringExtra("SESSION_ID")!=null){
              sessionId = getIntent.getStringExtra("SESSION_ID");
    }

    However, I would suggest you to use AppSharedPreferences to store
    your sessionId and get it from that wherever needed.


    使用全局类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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;
        }
    }

    您可以从所有其他类调用这个类的setter和getter。要做到这一点,您需要在每个活动中生成一个GlobalClass对象:

    1
    GlobalClass gc = (GlobalClass) getApplication();

    然后你可以打电话来,例如:

    1
    gc.getVitaminA()


    您可以通过3种方式在应用程序中的活动之间传递数据1、意图2.共享参考文献3、应用

    有意传递数据有一些限制。对于大量数据,您可以使用应用程序级数据共享,并将其存储在sharedPref中,使您的应用程序大小增加


    如果使用Kotlin:

    在MainActivity1中:

    1
    2
    3
    var intent=Intent(this,MainActivity2::class.java)
    intent.putExtra("EXTRA_SESSION_ID",sessionId)
    startActivity(intent)

    在MainActivity2中:

    1
    2
    3
    if (intent.hasExtra("EXTRA_SESSION_ID")){
        var name:String=intent.extras.getString("sessionId")
    }


    在Java中这样做:

    1
    startActivity(new Intent(this, MainActivity.class).putExtra("userId","2"));

    您的数据对象应该扩展parcelable或serializable类

    1
    2
    3
    Intent mIntent = new Intent(FirstActivity.this, SecondActivity.class);
    mIntent.putExtra("data", data);
    startActivity(mIntent);

    考虑使用单例保存所有活动都可以访问的会话信息。

    与附加变量和静态变量相比,此方法有几个优点:

  • 允许您扩展信息类,添加所需的新用户信息设置。您可以创建一个继承它的新类,或者只编辑信息类,而不需要在所有地方更改额外处理。
  • 使用方便-无需在每项活动中获取额外信息。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    public class Info {

        private static Info instance;
        private int id;
        private String name;

        //Private constructor is to disallow instances creation outside create() or getInstance() methods
        private Info() {

        }

        //Method you use to get the same information from any Activity.
        //It returns the existing Info instance, or null if not created yet.
        public static Info getInstance() {
            return instance;
        }

        //Creates a new Info instance or returns the existing one if it exists.
        public static synchronized Info create(int id, String name) {

            if (null == instance) {
                instance = new Info();
                instance.id = id;
                instance.name = name;
            }
            return instance;
        }
    }

  • 使用回调在活动之间进行新的实时交互:

    -步骤1:实现共享接口

    1
    2
    3
    public interface SharedCallback {
        public String getSharedText(/*you can define arguments here*/);
    }

    -步骤02:实现共享类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    final class SharedMethode {
        private static Context mContext;

        private static SharedMethode sharedMethode = new SharedMethode();

        private SharedMethode() {
            super();
        }

        public static SharedMethode getInstance() {
            return sharedMethode;
        }

        public void setContext(Context context) {
            if (mContext != null)
                return;

            mContext = context;
        }

        public boolean contextAssigned() {
            return mContext != null;
        }

        public Context getContext() {
            return mContext;
        }

        public void freeContext() {
            mContext = null;
        }
    }

    -步骤03:在第一个活动中使用代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class FirstActivity extends Activity implements SharedCallback {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.your_layout);

            // call playMe from here or there
            playMe();
        }

        private void playMe() {
            SharedMethode.getInstance().setContext(this);
            Intent intent = new Intent(this, SecondActivity.class);
            startActivity(intent);
        }

        @Override
        public String getSharedText(/*passed arguments*/) {
            return"your result";
        }

    }

    -步骤04:在secondActivity中完成游戏

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    public class SecondActivity extends Activity {

        private SharedCallback sharedCallback;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.your_layout);

            if (SharedMethode.getInstance().contextAssigned()) {
                if (SharedMethode.getInstance().getContext() instanceof SharedCallback)
                    sharedCallback = (SharedCallback) SharedMethode.getInstance().getContext();

                // to prevent memory leak
                SharedMethode.freeContext();
            }

            // You can now call your implemented methodes from anywhere at any time
            if (sharedCallback != null)
                Log.d("TAG","Callback result =" + sharedCallback.getSharedText());

        }

        @Override
        protected void onDestroy() {
            sharedCallback = null;
            super.onDestroy();
        }

    }
    • 步骤05:您还可以实现一个backword回调(从第一个回调到第二个回调),以从secondavctivity获取一些结果,或者调用一些方法

    要在所有活动中使用会话ID,可以执行以下步骤。

    1-在应用程序的应用程序文件中定义一个静态变量会话(它将保存会话ID的值)。

    2-现在使用类引用调用会话变量,在该类引用中获取会话ID值并将其赋给静态变量。

    3-现在您可以在任何地方使用这个会话ID值,只需通过调用静态变量


    在活动之间传递数据有多种方法,文档中有许多方法。

    在大多数情况下,intent.putenras就足够了。


    可以使用意向类在活动之间发送数据。它基本上是一条发送给操作系统的消息,您可以在其中描述数据流的源和目标。像从A到B活动的数据。

    在活动A(来源)中:

    1
    2
    3
    4
    5
    Intent intent = new Intent(A.this, B.class);

    intent.putExtra("KEY","VALUE");

    startActivity(intent);

    在活动B(目的地)->

    1
    2
    3
    Intent intent =getIntent();

    String data =intent.getString("KEY");

    在这里,您将获得键"key"的数据

    为了更好地使用,为了简单起见,键应该存储在一个类中,这将有助于最小化输入错误的风险。

    这样地:

    1
    2
    3
    public class Constants{
    public static String KEY="KEY"
    }

    现在在活动A中:

    1
    intent.putExtra(Constants.KEY,"VALUE");

    活动B:

    1
    String data =intent.getString(Constants.KEY);

    第一种方法:在当前活动中,当您创建要打开新屏幕的目标时:

    1
    2
    3
    4
      String value="xyz";
      Intent intent = new Intent(CurrentActivity.this, NextActivity.class);    
      intent.putExtra("key", value);
      startActivity(intent);

    然后在NextActivity in OnCreate方法中,检索从以前的活动传递的值:

    1
    2
    3
    4
    5
      if (getIntent().getExtras() != null) {
          String value = getIntent.getStringExtra("key");
          //The key argument must always match that used send and retrive value from one
          activity to another.
      }

    第二种方法:-您可以创建bundle对象并将值放入bundle中,然后从当前活动中有意放入bundle对象:-

    1
    2
    3
    4
    5
    6
      String value="xyz";
      Intent intent = new Intent(CurrentActivity.this, NextActivity.class);  
      Bundle bundle = new Bundle();
      bundle.putInt("key", value);  
      intent.putExtra("bundle_key", bundle);
      startActivity(intent);

    然后在NextActivity in OnCreate方法中,检索从以前的活动传递的值:

    1
    2
    3
    4
    5
    6
      if (getIntent().getExtras() != null) {
          Bundle bundle = getIntent().getStringExtra("bundle_key);    
          String value = bundle.getString("key");
          //The key argument must always match that used send and retrive value from one
          activity to another.
      }

    还可以使用bean类在使用序列化的类之间传递数据。


    //您的问题是要在登录后存储会话ID,并为要注销的每个活动提供该会话ID。

    //问题的解决方案是成功登录公共变量后,必须存储会话ID。每当需要注销会话ID时,可以访问该变量并将变量值替换为零。

    1
    2
    3
    4
    5
    //Serializable class

    public class YourClass  implements Serializable {
         public long session_id = 0;
    }

    在目的地活动中定义如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class DestinationActivity extends AppCompatActivity{

        public static Model model;
        public static void open(final Context ctx, Model model){
              DestinationActivity.model = model;
              ctx.startActivity(new Intent(ctx, DestinationActivity.class))
        }

        public void onCreate(/*Parameters*/){
               //Use model here
               model.getSomething();
        }
    }

    在第一个活动中,开始下面的第二个活动

    1
    DestinationActivity.open(this,model);


    我使用公共静态字段来存储活动之间的共享数据,但为了最小化其副作用,您可以:

    • 只生成一个字段,或者尽可能少,然后重用它们,使它们成为对象类型,并在接收活动中将其强制转换为所需类型。
    • 每当它们中的任何一个不再有用时,请在下一次分配之前将其显式设置为空,以便由垃圾收集器收集。


    这是将会话ID传递给所有活动的最简单方法之一。

    1
    2
    3
    Intent mIntent = new Intent(getApplicationContext(), LogoutActivity.class);
    mIntent.putExtra("session_id", session_id);
    startActivity(mIntent);

    因此,从logoutactivity可以获取会话的ID,这将进一步用于注销操作。

    希望这会有帮助……谢谢。


    在currentActivity.java中编写以下代码

    1
    2
    3
    Intent i = new Intent(CurrentActivity.this, SignOutActivity.class);
    i.putExtra("SESSION_ID",sessionId);
    startActivity(i);

    signoutactivity.java中的access sessionid如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sign_out);
        Intent intent = getIntent();

        // check intent is null or not
        if(intent != null){
            String sessionId = i.getStringExtra("SESSION_ID");
            Log.d("Session_id :" + sessionId);
        }
        else{
            Toast.makeText(SignOutActivity.this,"Intent is null", Toast.LENGTH_SHORT).show();
        }
    }


    我们可以通过两种方式将这些值传递给另一个活动(已经发布了相同类型的答案,但我发布的这里的编校代码试图通过意图传递)

    1.通过意图

    1
    2
    3
    4
    5
    6
      Activity1:
          startActivity(new Intent(getApplicationContext(),Activity2.class).putExtra("title","values"));

    InActivity 2:

    String recString= getIntent().getStringExtra("title");

    2.通过共享引用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
      Activity1:

    SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", 0);
     // 0 - for private mode
    Editor editor = pref.edit();
    editor.putString("key_name","string value"); // Storing string
    editor.commit(); // commit changes

    Activty2:
       SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", 0);

    pref.getString("key_name", null); // getting String