Fragment(2)

一、先记录一个问题:Fragment和Activity之间的通信。
(1)在Activity中操作Fragment
在activity中取得fragment的实例,通过这个实例进行通信,比如调用fragment中的方法等;
(2)在Fragment中操作Activity
通过getActivity()得到Activity的实例,进行操作。其中,必须记住的是接口回调的使用。
例:
Fragment1:

package com.wy.fragmentpractice.fragment;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.wy.fragmentpractice.R;

import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class Fragment1 extends Fragment {

    MClickListener mClickListener;
    @Bind(R.id.btnAdd)
    Button btnAdd;
    @Bind(R.id.btnDelete)
    Button btnDelete;

    //方法1:在onAttach()中实例化mClickListener
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        mClickListener = (MClickListener) activity;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment1, container, false);
        ButterKnife.bind(this, view);
        Log.i("TAG","onCreateView--Fragment1");
        return view;
    }
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        ButterKnife.unbind(this);
    }
    @OnClick({R.id.btnAdd, R.id.btnDelete})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btnAdd:
                mClickListener.setOnAddClick();
                break;
            case R.id.btnDelete://方法2:通过getActivity()得到宿主Activity,让Activity调用接口方法
                if (getActivity() instanceof MClickListener){
                    ((MClickListener) getActivity()).setOnDeleteClick();
                }
                break;
        }
    }
    public interface MClickListener {
        void setOnAddClick();
        void setOnDeleteClick();
    }
}

Fragment1中有横向排列的2个Button。
其中使用了一个强大的库:ButterKnife,用来简化findViewById()的代码,以后再记录着个库的详情。

Fragment2:

package com.wy.fragmentpractice.fragment;

import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import com.wy.fragmentpractice.R;

import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class Fragment2 extends Fragment {
    @Bind(R.id.btnToast)
    Button btnToast;

    MyToastListener myToastListener;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment2, container, false);
        ButterKnife.bind(this, view);
        Log.i("TAG","onCreateView--Fragment2");
        return view;
    }
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        ButterKnife.unbind(this);
    }
//方法3:通过fragment实例调用其公共方法,并且在activity中传入myToastListener实例。
    @OnClick(R.id.btnToast)
    public void onClick() {
        if (myToastListener==null) return;
        myToastListener.onToastClick();
    }

    public void setOnMyToastListener(MyToastListener m){
        this.myToastListener=m;
    }

    public interface MyToastListener{
        void onToastClick();
    }
}

Fragment2中只有一个Button。通过点击这个Button与Activity通信。

最后,Activity:

package com.wy.fragmentpractice.activity;

import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Toast;

import com.wy.fragmentpractice.R;
import com.wy.fragmentpractice.fragment.Fragment1;
import com.wy.fragmentpractice.fragment.Fragment2;

import butterknife.Bind;
import butterknife.ButterKnife;

public class MainActivity extends AppCompatActivity implements Fragment1.MClickListener {

    @Bind(R.id.tvText)
    TextView tvText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        FragmentManager fm=getFragmentManager();
        FragmentTransaction transaction=fm.beginTransaction();
        Fragment2 fragment2=new Fragment2();
        transaction.add(R.id.lnToast,fragment2);
        transaction.commit();

        fragment2.setOnMyToastListener(new Fragment2.MyToastListener() {
            @Override
            public void onToastClick() {
                Toast.makeText(MainActivity.this,"现在的大小是:"+tvText.getText().toString(),
                        Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public void setOnAddClick() {
        int a = Integer.parseInt(tvText.getText().toString()) - 1;
        String res = String.valueOf(a);
        tvText.setText(res);
    }

    @Override
    public void setOnDeleteClick() {
        int a = Integer.parseInt(tvText.getText().toString()) + 1;
        String res = String.valueOf(a);
        tvText.setText(res);
    }
}

activity的布局:

<?xml version="1.0" encoding="utf-8"?>
<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=".activity.MainActivity">

    <TextView
        android:id="@+id/tvText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:layout_centerHorizontal="true"
        android:textStyle="bold"
        android:text="1" />

    <fragment
        android:id="@+id/fragment1"
        android:name="com.wy.fragmentpractice.fragment.Fragment1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:layout="@layout/fragment1"
        android:layout_below="@+id/tvText"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="20dp"
        />

    <LinearLayout
        android:id="@+id/lnToast"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_below="@+id/fragment1"
        >

    </LinearLayout>
</RelativeLayout>

Activity中从上到下是:一个显示数字的TextView,一个静态的Fragment1,一个用来动态显示Fragment2的线性布局。点击Fragment1中的左边按钮,TextView显示数字-1,点击右边的按钮,TextView显示数字+1,点击Fragment2的按钮,弹出Toast,说明当前TextView中的数字是多少。

二、关于savedInstanceState
在测试的时候,多次旋转手机屏幕,会发现在AS打印出的Log信息中,onCreateView–Fragment1只会出现一次,而onCreateView–Fragment2会随着旋转的次数增加而增加,每转一次,增加一条。出现这种情况的原因是:当屏幕旋转时,MainActivity会重新启动,其中已存在的默认Fragment2也会随之重启,这就造成了当存在的Fragment2重启时,会在MainActivity中的onCreate()方法中创建一个Fragment2实例。不断旋转屏幕,Fragment2实例越来越多。静态使用的Fragment1为什么不会出现这种问题呢?我得想想。

解决办法是,在activity中的onCreate()方法中,判断savedInstanceState是否为null,从而决定是否创建Fragment实例。
修改MainActivity:

package com.wy.fragmentpractice.activity;

import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Toast;

import com.wy.fragmentpractice.R;
import com.wy.fragmentpractice.fragment.Fragment1;
import com.wy.fragmentpractice.fragment.Fragment2;

import butterknife.Bind;
import butterknife.ButterKnife;

public class MainActivity extends AppCompatActivity implements Fragment1.MClickListener {

    @Bind(R.id.tvText)
    TextView tvText;
    Fragment2 fragment2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        if (savedInstanceState==null) {
            FragmentManager fm = getFragmentManager();
            FragmentTransaction transaction = fm.beginTransaction();
             fragment2=new Fragment2();
            transaction.add(R.id.lnToast, fragment2);
            transaction.commit();
        }
        if (fragment2!=null){
            setOnClick(fragment2);
        }else{
            fragment2= (Fragment2) getFragmentManager().findFragmentById(R.id.lnToast);
            setOnClick(fragment2);
        }
    }

    private void setOnClick(Fragment2 fragment){
        fragment.setOnMyToastListener(new Fragment2.MyToastListener() {
            @Override
            public void onToastClick() {
                Toast.makeText(MainActivity.this,"现在的大小是:"+tvText.getText().toString(),
                        Toast.LENGTH_SHORT).show();
            }
        });
    }
    @Override
    public void setOnAddClick() {
        int a = Integer.parseInt(tvText.getText().toString()) - 1;
        String res = String.valueOf(a);
        tvText.setText(res);
    }

    @Override
    public void setOnDeleteClick() {
        int a = Integer.parseInt(tvText.getText().toString()) + 1;
        String res = String.valueOf(a);
        tvText.setText(res);
    }
}

代码能实现旋转屏幕正确显示,点击事件正确调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值