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数据传递(对象)引用不变问题的主要内容,如果未能解决你的问题,请参考以下文章

activity 给 fragment 传递参数

android activity中的变量怎么传值给fragment

如何将数据从 Activity 传递到已创建的 Fragment?

如何使用 TabLayout 将数据从 Activity 传递到 Fragment

从 android Activity 传递到 Fragment 的 Parcelable 对象

Android_在Fragment获取activity实现的接口以及通过bundle传递自定义对象