Fragment(2)
2016-04-24 16:50
447 查看
一、先记录一个问题:Fragment和Activity之间的通信。
(1)在Activity中操作Fragment
在activity中取得fragment的实例,通过这个实例进行通信,比如调用fragment中的方法等;
(2)在Fragment中操作Activity
通过getActivity()得到Activity的实例,进行操作。其中,必须记住的是接口回调的使用。
例:
Fragment1:
Fragment1中有横向排列的2个Button。
其中使用了一个强大的库:ButterKnife,用来简化findViewById()的代码,以后再记录着个库的详情。
Fragment2:
Fragment2中只有一个Button。通过点击这个Button与Activity通信。
最后,Activity:
activity的布局:
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:
代码能实现旋转屏幕正确显示,点击事件正确调用。
(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; } 4000 @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); } }
代码能实现旋转屏幕正确显示,点击事件正确调用。
相关文章推荐
- 3.2 Fragment的用法与通信大全
- Fragment与Activity的交互
- Fragment间通信
- Fragment和Activity之间的交互
- Android入门教程 fragment通信
- Android Fragment间的通信
- Android Fragment之间的通信
- JVM调优总结(3)垃圾回收面临的问题
- AndroidStudio 编译C/C++文件生成SO文件
- 字节序—大端和小端
- 使用jQuery.form插件,实现完美的表单异步提交
- maven的依赖
- 【转载】Gradle学习 第六章:构建脚本基础
- laravel环境搭建
- 类、对象(java基础知识六)
- jvm调优总结(2)
- node.js中npm的安装问题
- [剑指offer]矩形覆盖
- linux下yum程序包管理及源码安装
- 《Android 开发艺术探索》读书笔记六 IPC机制之Binder