Activity Fragment数据传递(对象)引用不变问题
Posted dx我是大雄
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Activity Fragment数据传递(对象)引用不变问题相关的知识,希望对你有一定的参考价值。
一.背景
一天写代码出了bug,Activity传给fragment的arraylist经过fragment中的修改居然会改变activity的arrayList(之前传给fragment的那个),当时我就震惊了,颠覆了我多年对android的认知。
一开始找到这篇博客:http://www.cnblogs.com/duanxz/p/3566221.html 里面说bundle是传递引用,但是事实不是,下面例子来证明 此处还是感谢大神
颠覆的常识
1.序列化反序列化前后对象内容一样但是肯定不是一个对象,同理ArrayList(目测Activity和Fragment之间并没有序列化反序列化)
2.直接打印ArrayList或者对象就可以看到他的存储地址(事实证明这是扯淡!!!)
3.直接打印对象或者arraylist,或者hashcode 只要打印结果一样,那么它们的引用肯定是指向一个地方。(详情看看toString源码,居然错了这么多年,惭愧啊)
二.来个栗子
1.MainActivity传递数据给SecondActivity
MainActivity.java
package com.example.administrator.text0212;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity
private ArrayList<User> userList = new ArrayList<>();
private ArrayList<User> userListUseBundle = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
System.out.println("xcqw onCreate");
setContentView(R.layout.activity_main);
for(int i = 0;i<2;i++)
User user = new User("大熊"+i+"号","man");
userList.add(user);
for(int i= 0;i<3;i++)
User user = new User("bundle"+i+"号","wonman");
userListUseBundle.add(user);
findViewById(R.id.bt_jump).setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("userListBundle",userListUseBundle);
intent.putParcelableArrayListExtra("userList",userList);
intent.putExtra("bundle",bundle);
System.out.println("xcqw MainActivity userList "+userList);
System.out.println("xcqw MainActivity userList hashCode "+userList.hashCode());
System.out.println("xcqw MainActivity userListBundle "+userListUseBundle);
System.out.println("xcqw MainActivity userListBundle hashCode "+userListUseBundle.hashCode());
startActivity(intent.setClass(MainActivity.this,SecondActivity.class));
);
@Override
protected void onResume()
super.onResume();
System.out.println("xcqw userList.size()"+userList.size());
System.out.println("xcqw userListUseBundle.size()"+userListUseBundle.size());
@Override
protected void onDestroy()
super.onDestroy();
System.out.println("xcqw onDestory");
SecondActivity.java
package com.example.administrator.text0212;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;
import java.util.ArrayList;
public class SecondActivity extends AppCompatActivity
private ArrayList<User> userList2 = new ArrayList<>();
private ArrayList<User> userListBundle2 = new ArrayList<>();
public ArrayList<User> userList;
private ArrayList<User> userListBundle;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Intent intent = getIntent();
userList = intent.getParcelableArrayListExtra("userList");
Bundle bundle = intent.getBundleExtra("bundle");
userListBundle = bundle.getParcelableArrayList("userListBundle");
System.out.println("xcqw SecondActivity userList " + userList);
System.out.println("xcqw SecondActivity userList hashCode " + userList.hashCode());
System.out.println("xcqw SecondActivity userListBundle " + userListBundle);
System.out.println("xcqw SecondActivity userListBundle hashCode " + userListBundle.hashCode());
userList2.addAll(userList);
userListBundle2.addAll(userListBundle);
System.out.println("xcqw SecondActivity userList2 " + userList);
System.out.println("xcqw SecondActivity userList2 hashCode " + userList.hashCode());
System.out.println("xcqw SecondActivity userListBundle2 " + userListBundle);
System.out.println("xcqw SecondActivity userListBundle2 hashCode " + userListBundle.hashCode());
if (userList2 == userList)
System.out.println("xcqw 前后一致1");
else
System.out.println("xcqw userList2 != userList");
System.out.println("xcqw userList.getClass()" + userList.getClass());
System.out.println("xcqw userList2.getClass()" + userList2.getClass());
System.out.println("xcqw SecondActivity userList " + userList);
System.out.println("xcqw SecondActivity userList hashCode " + userList.hashCode());
System.out.println("xcqw SecondActivity userList2 " + userList);
System.out.println("xcqw SecondActivity userList2 hashCode " + userList.hashCode());
if (userListBundle2 == userListBundle)
System.out.println("xcqw 前后一致2");
else
System.out.println("xcqw userListBundle2 != userListBundle");
System.out.println("xcqw SecondActivity userListBundle " + userListBundle);
System.out.println("xcqw SecondActivity userListBundle hashCode " + userListBundle.hashCode());
System.out.println("xcqw SecondActivity userListBundle2 " + userListBundle);
System.out.println("xcqw SecondActivity userListBundle2 hashCode " + userListBundle.hashCode());
if (userList.equals(userList2))
System.out.println("xcqw userList.equals(userList2)");
else
System.out.println("xcqw userList不equals(userList2)");
if (userListBundle.equals(userListBundle2))
System.out.println("xcqw userListBundle.equals(userListBundle2)");
else
System.out.println("xcqw userListBundle不equals(userListBundle2)");
findViewById(R.id.bt_add_fragment).setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
ContentFragment contentFragment = new ContentFragment();
Bundle bundle2 = new Bundle();
bundle2.putParcelableArrayList("userListActivity", userList);
bundle2.putString("succ", "成功了");
contentFragment.setArguments(bundle2);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fl_container, contentFragment);
fragmentTransaction.commitAllowingStateLoss();
);
findViewById(R.id.bt_get_userlist).setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
Toast.makeText(SecondActivity.this, "userList"+userList.size(), Toast.LENGTH_SHORT).show();
);
(1)没有覆写User equals和hashCode
package com.example.administrator.drawlayout;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by Administrator on 2017/2/12 0012.
*/
public class User implements Parcelable
private String name;
private String sex;
protected User(Parcel in)
name = in.readString();
sex = in.readString();
public static final Creator<User> CREATOR = new Creator<User>()
@Override
public User createFromParcel(Parcel in)
return new User(in);
@Override
public User[] newArray(int size)
return new User[size];
;
public String getName()
return name;
public void setName(String name)
this.name = name;
public String getSex()
return sex;
public void setSex(String sex)
this.sex = sex;
public User()
@Override
public int describeContents()
return 0;
@Override
public void writeToParcel(Parcel parcel, int i)
parcel.writeString(name);
parcel.writeString(sex);
// @Override
// public boolean equals(Object o)
// if (this == o) return true;
// if (!(o instanceof User)) return false;
//
// User user = (User) o;
//
// if (name != null ? !name.equals(user.name) : user.name != null) return false;
// return sex != null ? sex.equals(user.sex) : user.sex == null;
//
//
//
// @Override
// public int hashCode()
// int result = name != null ? name.hashCode() : 0;
// result = 31 * result + (sex != null ? sex.hashCode() : 0);
// return result;
//
打印结果:看起来很符合之前的“尝试” hashcode不一样,当然UserList2 != userList
MainActivity userList [com.example.administrator.text0212.User@8437750, com.example.administrator.text0212.User@af45d49]
MainActivity userList hashCode 186635194
MainActivity userListBundle [com.example.administrator.text0212.User@dee264e, com.example.administrator.text0212.User@c66436f, com.example.administrator.text0212.User@6f0b87c]
MainActivity userListBundle hashCode -766434790
//收到Activity传进来的数据
SecondActivity userList [com.example.administrator.text0212.User@6898cba, com.example.administrator.text0212.User@34dc76b]
SecondActivity userList hashCode -839526990
SecondActivity userListBundle [com.example.administrator.text0212.User@2a2b2c8, com.example.administrator.text0212.User@6f3f61, com.example.administrator.text0212.User@ab3ba86]
SecondActivity userListBundle hashCode -51512212
//Activity中 new 出来的 userList ,userListBundle2
SecondActivity userList2 [com.example.administrator.text0212.User@6898cba, com.example.administrator.text0212.User@34dc76b]
SecondActivity userList2 hashCode -839526990
SecondActivity userListBundle2 [com.example.administrator.text0212.User@2a2b2c8, com.example.administrator.text0212.User@6f3f61, com.example.administrator.text0212.User@ab3ba86]
SecondActivity userListBundle2 hashCode -51512212
userList2 != userList
userList.getClass()class java.util.ArrayList
userList2.getClass()class java.util.ArrayList
SecondActivity userList [com.example.administrator.text0212.User@6898cba, com.example.administrator.text0212.User@34dc76b]
SecondActivity userList hashCode -839526990
SecondActivity userList2 [com.example.administrator.text0212.User@6898cba, com.example.administrator.text0212.User@34dc76b]
SecondActivity userList2 hashCode -839526990
userListBundle2 != userListBundle
SecondActivity userListBundle [com.example.administrator.text0212.User@2a2b2c8, com.example.administrator.text0212.User@6f3f61, com.example.administrator.text0212.User@ab3ba86]
SecondActivity userListBundle hashCode -51512212
SecondActivity userListBundle2 [com.example.administrator.text0212.User@2a2b2c8, com.example.administrator.text0212.User@6f3f61, com.example.administrator.text0212.User@ab3ba86]
SecondActivity userListBundle2 hashCode -51512212
userList.equals(userList2)
userListBundle.equals(userListBundle2)
(2)重写equals
打印和之前一样
(3)重写equals和hashCode
MainActivity userList [com.example.administrator.text0212.User@1bfa9c50, com.example.administrator.text0212.User@1bfaa011]
MainActivity userList hashCode 2136183170
MainActivity userListBundle [com.example.administrator.text0212.User@7939505b, com.example.administrator.text0212.User@7939541c, com.example.administrator.text0212.User@793957dd]
MainActivity userListBundle hashCode 928096571
SecondActivity userList [com.example.administrator.text0212.User@1bfa9c50, com.example.administrator.text0212.User@1bfaa011]
SecondActivity userList hashCode 2136183170
SecondActivity userListBundle [com.example.administrator.text0212.User@7939505b, com.example.administrator.text0212.User@7939541c, com.example.administrator.text0212.User@793957dd]
SecondActivity userListBundle hashCode 928096571
SecondActivity userList2 [com.example.administrator.text0212.User@1bfa9c50, com.example.administrator.text0212.User@1bfaa011]
SecondActivity userList2 hashCode 2136183170
SecondActivity userListBundle2 [com.example.administrator.text0212.User@7939505b, com.example.administrator.text0212.User@7939541c, com.example.administrator.text0212.User@793957dd]
SecondActivity userListBundle2 hashCode 928096571
userList2 != userList
userList.getClass()class java.util.ArrayList
userList2.getClass()class java.util.ArrayList
SecondActivity userList [com.example.administrator.text0212.User@1bfa9c50, com.example.administrator.text0212.User@1bfaa011]
SecondActivity userList hashCode 2136183170
SecondActivity userList2 [com.example.administrator.text0212.User@1bfa9c50, com.example.administrator.text0212.User@1bfaa011]
SecondActivity userList2 hashCode 2136183170
userListBundle2 != userListBundle
SecondActivity userListBundle [com.example.administrator.text0212.User@7939505b, com.example.administrator.text0212.User@7939541c, com.example.administrator.text0212.User@793957dd]
SecondActivity userListBundle hashCode 928096571
SecondActivity userListBundle2 [com.example.administrator.text0212.User@7939505b, com.example.administrator.text0212.User@7939541c, com.example.administrator.text0212.User@793957dd]
SecondActivity userListBundle2 hashCode 928096571
userList.equals(userList2)
userListBundle.equals(userListBundle2)
这个再一次证明内存地址是否一样跟hashcode没有任何关系,也跟直接打印对象得到的值没关系,即使两者相等也不会一样
第一个例子说明:
1.hashcode和直接打印对象跟内存地址(也就是引用)没有任何关系
2.Bundle传递也是传数据不是传引用!!!
2.Activity传递数据到Fragment
(1)没有覆写equals和hashCode
Content成功了
contentFragment userArrayList [com.example.administrator.text0212.User@6898cba, com.example.administrator.text0212.User@34dc76b]
contentFragment userArrayList hashcode -839526990
contentFragment userArrayList.toString [com.example.administrator.text0212.User@6898cba, com.example.administrator.text0212.User@34dc76b]
((SecondActivity)getActivity()).userList == userArrayList
contentFragment otherUserList [com.example.administrator.text0212.User@6898cba, com.example.administrator.text0212.User@34dc76b]
contentFragment otherUserList hashcode -839526990
contentFragment otherUserList.toString [com.example.administrator.text0212.User@6898cba, com.example.administrator.text0212.User@34dc76b]
((SecondActivity)getActivity()).userList != otherUserList
userArrayListSize2
clear userArrayList userArrayListSize0
另外点击另外一个按钮获取Activity中的userList 的size发现也是0
可以看到otherUserList和userArrayList虽然打印直接打印的值和hascode的值一样,但是并没有什么软用,他们还是 !=
还有就是证明了一点就是Activity传递数据给fragment传的是引用
(2)覆写equals
所有结果和上面一样
(3)覆写equals和hashcode
只是打印的hashcode值变了,结果没有变
三.总结
1.hashCode和直接打印对象的值与内存地址没有任何关系
2.Activity与Fragment数据传递会保持对象的引用,不管是parcelable还是Serizable(但是不知道为什么???待研究)
3.判断对象引用是否相同目前发现有且只有一个 obj1 == obj2
以上是关于Activity Fragment数据传递(对象)引用不变问题的主要内容,如果未能解决你的问题,请参考以下文章
android activity中的变量怎么传值给fragment
如何将数据从 Activity 传递到已创建的 Fragment?
如何使用 TabLayout 将数据从 Activity 传递到 Fragment