一、先記錄一個問題: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);
}
}
代碼能實現旋轉屏幕正確顯示,點擊事件正確調用。