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);
    }
}

代碼能實現旋轉屏幕正確顯示,點擊事件正確調用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章