常见的Android数据传递方法汇总

一、Intent与Bundle

1、Activty与Activity

1.1、传递简单数据

(1) 传单个值(以String类型为例)

  • 发送数据
	Intent intent = new Intent(A.this, B.class);
	intent.putExtra("key", value);
	startActivity(intent);
  • 接收数据
	// 获取数据的方法需要根据传递的数据类型而定
	Intent reIntent = getIntent();
	String tempStr = reIntent.getStringExtra("key");

(2)传多个值

  • 发送数据
	Intent intent = new Intent(A.this, B.class);
	Bundle bd = new Bundle();
	bd.putString("name", "张三");
	bd.putInt("age", 23);
	intent.putExtras(bd);
	startActivity(intent);
  • 接收数据
	Intent reIntent = getIntent();
	Bundle reBd = reIntent.getExtras();
	String name = reBd.getString("name");
	int age = reBd.getInt("age");
1.2、传递复杂数据
  1. 数组

(1)纯Intent

  • 传递数据
	Intent intent = new Intent(A.this, B.class);
	intent.putExtra("arrName", new String[]{"张三", "李四", "王五"});
	startActivity(intent);
  • 接收数据
	Intent reIntent = getIntent();
	reIntent.getStringArrayExtra("arrName");

(2)Intent和Bundle

  • 传递数据
	Intent intent = new Intent(A.this, B.class);
	Bundle bd = new Bundle();
	bd.putStringArray("arrName", new String[]{"张三", "李四", "王五"});
	intent.putExtras(bd);
	startActivity(intent);
  • 接收数据
	Intent reIntent = getIntent();
	Bundle reBd = reIntent.getExtras();
	reBd.getStringArray("arrName");
  1. 集合

(1)List<基本数据类型或String、Integer>

单用Intent或Intent与Bundle结合都可以

  • 发送数据
	ArrayList<String> strList = new ArrayList<>();
	stringList.add("张三");
	stringList.add("李四");
	Intent listIntent = new Intent(A.this, B.claaa);
	listIntent.putStringArrayListExtra("strList", strList);
	startActivity(listIntent);
  • 接收数据
	Intent reIntent = getIntent();
	reIntent.getStringArrayListExtra("strList");

(2)List<自定义对象>

  • 首先自定义对象要实现Serializable接口
import java.io.Serializable;

public class Student implements Serializable {

    private String name;
    private int age;
    private String sex;
    private String grade;
    private String school;

    public Student(String name, int age, String sex, String grade, String school) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.grade = grade;
        this.school = school;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }
}
  • 发送数据
	Intent intent = new Intent(A.this, B.class);
	List<Student> studentList = new ArrayList<>();
	studentList.add(new Student("张三", 25, "男", "大三", "广州大学"));
	studentList.add(new Student("李四", 24, "男", "大二", "贵州大学"));
	studentList.add(new Student("李红", 27, "男", "大四", "清华大学"));
	studentList.add(new Student("王五", 23, "男", "大一", "北京大学"));
	
	intent.putExtra("studentList", (Serializable) studentList);
	startActivity(intent);
  • 接收数据
	Intent reIntent = getIntent();
	List<Student> reStudentList = (List<Student>) reIntent.getSerializableExtra("studentList");
  1. 对象

(1)使用Serializable序列化对象;

  • 序列化对象
import java.io.Serializable;

/**
 * 学生
 */
public class Student implements Serializable {

    private String name;
    private int age;
    private String sex;
    private String grade;
    private String school;

    public Student(String name, int age, String sex, String grade, String school) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.grade = grade;
        this.school = school;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }
}
  • 发送数据
	Intent intent = new Intent(A.this, B.class);
	Student stu1 = new Student("张三", 25, "男", "大三", "广州大学");
	intent.putExtra("stu1", stu1);
	startActivity(intent);
  • 接收数据
	Intent reIntent = getIntent();
	Student stu1 = (Student) reIntent.getSerializableExtra("stu1");

(2)使用Parcelable序列化对象;

  • 序列化对象
import android.os.Parcel;
import android.os.Parcelable;

/**
 * 课程
 */
public class Course implements Parcelable {

    private String courseName;
    private String courseType;

    public Course() {
    }

    public Course(String courseName, String courseType) {
        this.courseName = courseName;
        this.courseType = courseType;
    }

    public String getCourseName() {
        return courseName;
    }

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }

    public String getCourseType() {
        return courseType;
    }

    public void setCourseType(String courseType) {
        this.courseType = courseType;
    }

    @Override
    public int describeContents() {
        // 内容描述,返回0就可以
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        // 将Course对象转化成Parcel,
        // dest是目标Parcel,
        // flags标志object是如何被写的。
        // 0或者PARCELABLE_WRITE_RETURN_VALUE
        dest.writeString(courseName);
        dest.writeString(courseType);
    }

    public static final Creator<Course> CREATOR = new Creator<Course>() {
        @Override
        public Course createFromParcel(Parcel in) {
            // 将Parcel映射成Course对象
            Course mCourse = new Course();
            // 同种数据类型,顺序为先进先出
            mCourse.courseName = in.readString();
            mCourse.courseType = in.readString();
            return mCourse;
        }

        @Override
        public Course[] newArray(int size) {
            return new Course[size];
        }
    };
}
  • 发送数据
	Intent intent = new Intent(A.this, B.class);
	Course course = new Course("语文", "文科");
    intent.putExtra("course", course);
    startActivity(intent);
  • 接收数据
	Intent reIntent = getIntent();
	Course mCourse = reIntent.getParcelableExtra("course");

(3)使用Gson将对象转化为Json格式再传递。

  • 导入依赖包
	//添加Gson依赖
    implementation 'com.google.code.gson:gson:2.8.8'
  • 定义对象
public class Book {

    private String bookName;
    private String bookAuthor;

    public Book(String bookName, String bookAuthor) {
        this.bookName = bookName;
        this.bookAuthor = bookAuthor;
    }

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public String getBookAuthor() {
        return bookAuthor;
    }

    public void setBookAuthor(String bookAuthor) {
        this.bookAuthor = bookAuthor;
    }
}
  • 发送数据
	Intent intent = new Intent(A.this, B.class);
	Book book = new Book("西游记", "吴承恩");
	intent.putExtra("book", new Gson().toJson(book));
	startActivity(intent);
  • 接收数据
	Intent reIntent = getIntent();
	String bookJson = reIntent.getStringExtra("book");
	Book mBook = new Gson().fromJson(bookJson, Book.class);

2、Activity与Fragment

2.1、Activity传递数据给Fragment

1、通过构造函数传递

  • step1:在RightFragment.java中重载构造函数
	private String mData;
    public RightFragment(String data) {
        mData = data;
    }
  • step2:在MainActivityFour.java中创建Fragment实例的同时,通过构造函数将数据传递过去
    RightFragment rightFragment = new RightFragment("GetDataFromMainTwo");
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    transaction.replace(R.id.fl_right, rightFragment, "rightFragment");
    transaction.commit();

2、通过setArguments()传递

  • step1:在MainActivityFour.java初始化Fragment时,使用setArgments传递数据
	RightFragment rightFragment = new RightFragment();
	
	Bundle bundle = new Bundle();
    bundle.putString("main_data", "GetDataFromMainThree");
    rightFragment.setArguments(bundle);
    
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    transaction.replace(R.id.fl_right, rightFragment, "rightFragment");
    transaction.commit();
	
  • step2:在RightFragment.java中获取数据
	@Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (isAdded()) {
            String getData = "";
            Bundle bundle = getArguments();
            if (bundle != null)
                getData = getArguments().getString("main_data");
            tvShowContent.setText(getData);
        }
    }

3、Fragment中定义方法再调用

  • step1:在RightFragment.java中定义一个接收数据的方法
	public void setData(String dataMsg) {
        tvShowContent.setText(dataMsg);
    }
  • step2:在MianActivityFour.java中发送数据
	rightFragment.setData("GetDataFromMain");
2.2、Fragment传递数据给Activity

通过接口回调获取数据

  • step1:在RightFragment.java中定义一个接口以及设置接口的方法
	public onDataTransmissionListener mListener;
	
	public interface onDataTransmissionListener {
		public void dataTransmission(String data);
	}
	
	public void setOnDataTransmissionListener(onDataTransmissionListener mListener) {
	    this.mListener = mListener;
	}
  • step2:在RightFragment.java中通过接口传递数据
	if (mListener != null) {
		mListener.dataTransmission(btnTextTwo.getText().toString());
	}
  • step3:在MianActivityFour.java中设置Fragment并监听RightFragment.java的接口
    RightFragment rightFragment = new RightFragment();
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    transaction.replace(R.id.fl_right, rightFragment, "rightFragment");
    transaction.commit();

    rightFragment.setOnDataTransmissionListener(new RightFragment.onDataTransmissionListener() {
        @Override
        public void dataTransmission(String data) {
            String fgData = data; //获取Fragment传过来的内容
        }
    });

3、Fragment与Fragment

先创建一个简单的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivityFour"
    android:orientation="horizontal">

    <FrameLayout
        android:id="@+id/fl_left"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"/>

    <FrameLayout
        android:id="@+id/fl_right"
        android:layout_width="0dp"
        android:layout_weight="2"
        android:layout_height="match_parent"/>

</LinearLayout>
3.1、获取Fragment的id或Tag

核心代码如下,

  • step1:在MainActivityFour.java中设置Fragment
	LeftFragment leftFragment = new LeftFragment();
    RightFragment rightFragment = new RightFragment();
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    transaction.replace(R.id.fl_left, leftFragment, "leftFragment");
    transaction.replace(R.id.fl_right, rightFragment, "rightFragment");
    transaction.commit();
  • step2:在RightFragment.java中定义一个接收数据的方法
	public void setData(String dataMsg) {
	    tvShowContent.setText(dataMsg);
	}
  • step3:在LeftFragment.java中根据FragmentID或FragmentTag获取RightFragment对象
	RightFragment rightFragment = (RightFragment) getActivity()
                	.getSupportFragmentManager().findFragmentById(R.id.fl_right);
    rightFragment.setData(btnTextOne.getText().toString());

	RightFragment rightFragment = (RightFragment) getActivity()
                    .getSupportFragmentManager().findFragmentByTag("rightFragment");
    rightFragment.setData(btnTextOne.getText().toString()); 
3.2、接口回调
  • step1:在LeftFragment.java中定义一个接口以及设置接口的方法
	public onDataTransmissionListener mListener;
	
	public interface onDataTransmissionListener {
		public void dataTransmission(String data);
	}
	
	public void setOnDataTransmissionListener(onDataTransmissionListener mListener) {
	    this.mListener = mListener;
	}
  • step2:在LeftFragment.java中通过接口传递数据
	if (mListener != null) {
		mListener.dataTransmission(btnTextTwo.getText().toString());
	}
  • step3:在RightFragment.java中定义一个接收数据的方法
	public void setData(String dataMsg) {
		tvShowContent.setText(dataMsg);
	}
  • step4:在MianActivityFour.java中设置Fragment并监听LeftFragment.java的接口
	LeftFragment leftFragment = new LeftFragment();
    RightFragment rightFragment = new RightFragment();
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    transaction.replace(R.id.fl_left, leftFragment, "leftFragment");
    transaction.replace(R.id.fl_right, rightFragment, "rightFragment");
    transaction.commit();

    leftFragment.setOnDataTransmissionListener(new LeftFragment.onDataTransmissionListener() {
        @Override
        public void dataTransmission(String data) {
            rightFragment.setData(data);
        }
    });

二、EventBus

上述Activity与Activity、Activity与Fragment以及Frament与Fragment之间的通信,都可以使用EventBus实现,具体步骤如下:

1、在app目录下的build.gradle文件中添加eventbus依赖;

implementation 'org.greenrobot:eventbus:3.0.0'

2、创建EventBus信息传递类;

public class EventInit {

    private String name;
    private String age;
    private String sex;
    private String grade;
    private String school;

    public EventInit(String name, String age, String sex, String grade, String school) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.grade = grade;
        this.school = school;
    }

    public String getAllValue() {
        return "name: " + name
                + "\nage: " + age
                + "\nsex: " + sex
                + "\ngrade: " + grade
                + "\nschool: " + school;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }
}

3、在发送消息的Activty或Fragment中使用下面代码;

	EventBus.getDefault().post(new EventInit(name, age, sex, grade, school));

4、在接收数据的Activity或Fragment中注册和注销EventBus,并接收消息;

一般建议:

(1)在onStart()中注册EventBus.

	@Override
    protected void onStart() {
        super.onStart();
        //注册EventBus 接收数据
        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this);
        }
    }

(2)在onDestroy()中注销EventBus.

	@Override
    protected void onDestroy() {
        super.onDestroy();
        //注销事件接收
        EventBus.getDefault().unregister(this);
    }

(3)定义接收消息的方法

	// 接收消息(post)
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEventInit(EventInit eventInit) {
        try {
            String allValue = eventInit.getAllValue();
            //更改TextView内容
            tvReceiveText.setText(allValue);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

5、运行程序后,可能会出现如下问题;

(1)在Run窗口可以看到下面的提示,但并不会报错;

	EventBusNo subscribers registered for event class

(2)以上问题是由于EventBus不适合向一个不存在于activity栈中的activity发送消息,这样是失败的,fragment同理。

例如:

情况1:一个activity 还没有生成,就post,肯定报这样的错;

情况2:一个activity曾经生成了,但是不在activity栈中了,也是收不到消息的

情况3:生命周期的问题。如果是在onStop()方法中注销了EventBus,而在特殊情况下恰好调用了接收消息的Activty或Fragment中的onStop()方法,这也就出现了上述的问题。

6、解决方法;

(1)依旧使用上述的post方式发送消息,不过需要加上延时操作,如下:

	//延时发送数据
  new Thread(new Runnable() {
      @Override
      public void run() {
          try {
              Thread.sleep(500);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
          EventBus.getDefault().post(new EventInit(name, age, sex, grade, school));
      }
  }).start();

(2)或者使用postSticky方式替换post方式发送消息,如下:

	//使用粘性事件
	EventBus.getDefault().postSticky(new EventInit(name, age, sex, grade, school));

在接收消息的Activity或Fragment中定义接收消息的方法:

// 接收消息(postStick)
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void onEventInitTwo(EventInit eventInit) {
        try {
            String allValue = eventInit.getAllValue();
            //更改TextView内容
            tvReceiveText.setText(allValue);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

(3)post与postSticky相比,若post事件没有被订阅,则该事件会被流传,即作废;而postSicky是将完整的事件放到内存中,待EventBus注册时再从内存中获取该事件,然后包装成一个新的post事件进行发布,由于此时EventBus注册已执行完毕,所以postSticky事件可以正常使用。

你可能感兴趣的:(Android,android)