Android 通过mainActivity在片段之间传递数据时出错

Android 通过mainActivity在片段之间传递数据时出错,android,android-fragments,Android,Android Fragments,在下面的代码中,我有一个主活动,它承载两个片段Frag1和Frag2,如下所示,Frag1实现sensorEventListener,当单击Frag1中的按钮时,传感器读数应传递到Frag2 为此,我创建了一个接口onSendListener,它位于onatch中,设置为sendValues=(onSendListener)活动。而mainActivity实现onSendListener,如下面发布的mainActivity的代码所示,在onSendListener中,我将读数传递给Frag2

在下面的代码中,我有一个主活动,它承载两个
片段
Frag1
Frag2
,如下所示,
Frag1
实现
sensorEventListener
,当单击
Frag1
中的
按钮时,传感器读数应传递到
Frag2

为此,我创建了一个接口
onSendListener
,它位于
onatch
中,设置为
sendValues=(onSendListener)活动。而
mainActivity
实现
onSendListener
,如下面发布的
mainActivity
的代码所示,在
onSendListener
中,我将读数传递给
Frag2

在运行时,我收到下面发布的
logCat
错误

请让我知道我做错了什么

**主要活动**:

public class MainActivity extends Activity implements onSendListener {

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

/**
 * to send values from frag1 to frag2 through mainActivity. use bundle.
 */
@Override
public void onSendValues(float x, float y, float z) {
    // TODO Auto-generated method stub
    Bundle b = new Bundle();
    b.putFloat("x", x);
    b.putFloat("y", y);
    b.putFloat("z", z);

    Frag2 frag2 = new Frag2();
    frag2.setArguments(b);
}
}

**框架**:

public class Frag1 extends Fragment implements SensorEventListener {

private SensorManager sensorManager;
TextView tvAccX;
TextView tvAccY;
TextView tvAccZ;

private float x = 0.0f;
private float y = 0.0f;
private float z = 0.0f;

private void setAccX(float x) {
    this.x = x;
}
private float getAccX() {
    return this.x;
}

private void setAccY(float y) {
    this.y = y;
}
private float getAccY() {
    return this.y;
}

private void setAccZ(float z) {
    this.z = z;
}
private float getAccZ() {
    return this.z;
}

Button btnSend;
onSendListener sendValues;

@Override
public void onAttach(Activity activity) {
    // TODO Auto-generated method stub
    super.onAttach(activity);

    sendValues = (onSendListener) activity;
    sensorManager = (SensorManager) getActivity().getSystemService(Context.SENSOR_SERVICE);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    View view = inflater.inflate(R.layout.frag_1, container, false);

    tvAccX = (TextView) view.findViewById(R.id.tv_accX_value);
    tvAccY = (TextView) view.findViewById(R.id.tv_accY_value);
    tvAccZ = (TextView) view.findViewById(R.id.tv_accZ_value);
    btnSend = (Button) view.findViewById(R.id.btn_send);

    return view;
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onViewCreated(view, savedInstanceState);


}

@Override
public void onSensorChanged(SensorEvent event) {
    // TODO Auto-generated method stub
    switch (event.sensor.getType()) {
    case Sensor.TYPE_ACCELEROMETER:
        showAccReadings(event);
        break;

    default:
        break;
    }
}

private void showAccReadings(SensorEvent event) {
    // TODO Auto-generated method stub
    float[] values = event.values;

    float x = values[0];
    float y = values[1];
    float z = values[2];

    setAccX(x);
    setAccY(y);
    setAccZ(z);

    tvAccX.setText(String.valueOf(x));
    tvAccY.setText(String.valueOf(y));
    tvAccZ.setText(String.valueOf(z));
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
    // TODO Auto-generated method stub

}

@Override
public void onResume() {
    // TODO Auto-generated method stub
    super.onResume();

    Sensor accSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    sensorManager.registerListener(this, accSensor, sensorManager.SENSOR_DELAY_FASTEST);

    btnSend.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            sendValues.onSendValues(getAccX(), getAccY(), getAccZ());
        }
    });
}

@Override
public void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    sensorManager.unregisterListener(this);
}
}

**框架2**:

public class Frag2 extends Fragment {

float x;
float y;
float z;

TextView tvX;
TextView tvY;
TextView tvZ;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // TODO Auto-generated method stub

    x = getArguments().getFloat("x");
    y = getArguments().getFloat("y");
    z = getArguments().getFloat("z");

    View view = inflater.inflate(R.layout.frag_2, container, false);

    tvX = (TextView) view.findViewById(R.id.tv_accX2_label);
    tvY = (TextView) view.findViewById(R.id.tv_accY2_label);
    tvZ = (TextView) view.findViewById(R.id.tv_accZ2_label);

    return view;
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onViewCreated(view, savedInstanceState);

    tvX.setText(String.valueOf(x));
    tvY.setText(String.valueOf(y));
    tvZ.setText(String.valueOf(z));
}
}

**mainActivity.xml**:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}">

<fragment
    android:name="com.example.fragmentcommunication_00.Frag1"
    android:id="@+id/frag_1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"/>

<fragment
    android:name="com.example.fragmentcommunication_00.Frag2"
    android:id="@+id/frag_2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="50dp"
    android:layout_centerHorizontal="true"
    android:layout_below="@id/frag_1"/>

显然,系统无法创建第二个片段,因为它需要在不同时间设置的参数,而不是在创建布局时设置的参数。ActivityManager在活动中调用onCreate(),在片段中调用onCreate()和onCreateView()。但是,在创建时不会调用设置参数的onSendValues()方法

为片段设置参数不是片段之间动态通信的解决方案。它仅适用于视图的初始创建

您必须在第二个片段中创建public方法,并在需要将数据从活动传递给它时从活动调用它。因此,通信方案是:Fragment1通过活动中的接口调用方法->Fragment2中的活动调用方法

你可以核对我的答案

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView 
    android:id="@+id/tv_accX_label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentStart="true"
    android:text="Acc[X]: "/>
<TextView 
    android:id="@+id/tv_accX_value"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/tv_accX_label"
    android:gravity="center_vertical|center_horizontal"/>

<TextView 
    android:id="@+id/tv_accY_label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentStart="true"
    android:layout_below="@id/tv_accX_label"
    android:text="Acc[Y]: "/>
<TextView 
    android:id="@+id/tv_accY_value"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toEndOf="@id/tv_accY_label"
    android:layout_below="@id/tv_accX_label"
    android:gravity="center_vertical|center_horizontal"/>

<TextView 
    android:id="@+id/tv_accZ_label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentStart="true"
    android:layout_below="@id/tv_accY_label"
    android:text="Acc[Z]: "/>
<TextView 
    android:id="@+id/tv_accZ_value"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toEndOf="@id/tv_accZ_label"
    android:layout_below="@id/tv_accY_label"
    android:gravity="center_vertical|center_horizontal"/>

<Button 
    android:id="@+id/btn_send"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@id/tv_accZ_label"
    android:gravity="center_vertical|center_horizontal"
    android:text="send to frag_2"/>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView 
    android:id="@+id/tv_accX2_label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentStart="true"
    android:text="Acc[X]: "/>
<TextView 
    android:id="@+id/tv_accY2_label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentStart="true"
    android:layout_below="@+id/tv_accX2_label"
    android:text="Acc[Y]: "/>
<TextView 
    android:id="@+id/tv_accZ2_label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentStart="true"
    android:layout_below="@+id/tv_accY2_label"
    android:text="Acc[Z]: "/>
01-26 10:51:24.416: E/AndroidRuntime(4546): FATAL EXCEPTION: main
01-26 10:51:24.416: E/AndroidRuntime(4546): Process: com.example.fragmentcommunication_00, PID: 4546
01-26 10:51:24.416: E/AndroidRuntime(4546): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.fragmentcommunication_00/com.example.fragmentcommunication_00.MainActivity}: android.view.InflateException: Binary XML file line #14: Error inflating class fragment
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2282)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2340)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.app.ActivityThread.access$800(ActivityThread.java:157)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1247)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.os.Handler.dispatchMessage(Handler.java:102)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.os.Looper.loop(Looper.java:157)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.app.ActivityThread.main(ActivityThread.java:5293)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at java.lang.reflect.Method.invokeNative(Native Method)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at java.lang.reflect.Method.invoke(Method.java:515)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at dalvik.system.NativeStart.main(Native Method)
01-26 10:51:24.416: E/AndroidRuntime(4546): Caused by: android.view.InflateException: Binary XML file line #14: Error inflating class fragment
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:719)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.view.LayoutInflater.rInflate(LayoutInflater.java:761)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.view.LayoutInflater.inflate(LayoutInflater.java:498)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.view.LayoutInflater.inflate(LayoutInflater.java:398)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.view.LayoutInflater.inflate(LayoutInflater.java:354)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:340)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.app.Activity.setContentView(Activity.java:1973)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at com.example.fragmentcommunication_00.MainActivity.onCreate(MainActivity.java:17)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.app.Activity.performCreate(Activity.java:5389)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2246)
01-26 10:51:24.416: E/AndroidRuntime(4546):     ... 11 more
01-26 10:51:24.416: E/AndroidRuntime(4546): Caused by: java.lang.NullPointerException
01-26 10:51:24.416: E/AndroidRuntime(4546):     at com.example.fragmentcommunication_00.Frag2.onCreateView(Frag2.java:25)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.app.Fragment.performCreateView(Fragment.java:1700)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:866)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1040)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.app.FragmentManagerImpl.addFragment(FragmentManager.java:1142)
0   1-26 10:51:24.416: E/AndroidRuntime(4546):  at android.app.Activity.onCreateView(Activity.java:4935)
01-26 10:51:24.416: E/AndroidRuntime(4546):     at android.view.LayoutInflater.createViewFromTag(LayoutI    nflater.java:695)