Fragment以及懒加载
1、Fragments
Fragment是Activity中用户界面的一个行为或者是一部分,你可以在一个单独的Activity上把多个Fragment组合成为一个多区域的UI,并且可以在多个Activity中再次使用。可以认为Fragment是Activity的一个模块零件,他有自己的生命周期,接受他自己的输入事件,并且可以在Activity运行时添加或者删除。
两个概念:
Fragment、宿主
fragment的生命周期只接受其宿主activity的生命周期的影响。例如,一旦activity被暂停,它里面所有的fragment也会被暂停,一旦activity被销毁,它里面的所有fragment也会被销毁。
2、创建Fragment
要创建一个fragment,必须创建一个fragment的子类(或是继承自他的子类),fragment类的代码看起来很像activity,他与activity一样都有回调函数,例如onCreate,onStart,onPause和onStop,事实上,如果你正在讲一个现成的Android应用转而使用Fragment来实现,可以将代码从activity的回调函数移植到各自的fragment中。
除了基类fragment,还有几个可能会继承的子类:
DialogFragment、ListFragment、PreferenceFragment
3、添加用户界面
fragment常被用作activity用户界面的一部分,并且将本身的布局够见到activity中去。
将fragment添加到activity有两种方式:
1)在activity的布局文件里声明fragment
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"> <fragment
android:id="@+id/fragTitle"
android:name="com.wzh.pushdemo.fragment.TitleFragment"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1" /> <fragment
android:id="@+id/fragContent"
android:name="com.wzh.pushdemo.fragment.ContentFragment"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="3" /> </LinearLayout>
2)通过编码将fragment添加到已存在的ViewGroup中
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"> <fragment
android:id="@+id/fragTitle"
android:name="com.wzh.pushdemo.fragment.TitleFragment"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1" /> <FrameLayout
android:id="@+id/framLayout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3">
</FrameLayout> </LinearLayout>
public class MainActivity extends Activity {
TitleFragment titleFragment;
ContentFragment contentFragment;
FrameLayout framLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//通过fragmentManager(Fragment管理器)获取fragment实例
// titleFragment = (TitleFragment) getFragmentManager().findFragmentById(R.id.fragTitle);
// contentFragment = (ContentFragment) getFragmentManager().findFragmentById(R.id.fragContent);
framLayout = (FrameLayout) findViewById(R.id.framLayout);
/**
* 通过代码添加Fragment
*/
FragmentManager fm = getFragmentManager();
//开启一个事务
FragmentTransaction ft = fm.beginTransaction();
contentFragment = new ContentFragment();
//添加Fragment
ft.add(R.id.framLayout, contentFragment);
// ft.remove(); //删除
// ft.replace();//替换
//提交事务
ft.commit();
}
}
- transaction.add() 往Activity中添加一个
- Fragment transaction.remove() 从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈,这个Fragment实例将会被销毁。
- transaction.replace() 使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体
- transaction.hide() 隐藏当前的Fragment,仅仅是设为不可见,并不会销毁,
- transaction.show() 显示之前隐藏的Fragment
- detach()
会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护。 - attach()
重建view视图,附加到UI上并显示。 - transatcion.commit()
提交一个事务
4、管理Fragments
想要管理activity中的fragment,可以使用FragmentManager,可以通过在activity中调用getFragmentManager()获得。
使用FragmentManger可以做如下事情,包括:
(1)使用findFragmentById()(用于在activity不居中提供有界面的fragment)或者findFragmentByTag()获取activity中存在的fragment(用于有界面或者没有界面的fragment)
(2)使用popBackStack()(模仿用户的back命令)从后台栈弹出fragment
(3)使用addOnBackStackChangedListener()注册一个监听后台栈变化的监听器
public class PopBackActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pop_back);
}
public void oneClick(View view) {
PopBackFragment p1 = new PopBackFragment("one");
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.content, p1);
//把当前fragment添加到Activity栈
ft.addToBackStack(null);
ft.commit();
}
public void twoClick(View view) {
//用构造方法传值,有问题
PopBackFragment p1 = new PopBackFragment("two");
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.content, p1);
//把当前fragment添加到Activity栈
ft.addToBackStack(null);
ft.commit();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (getFragmentManager().getBackStackEntryCount() == 0) {
finish();
} else {
getFragmentManager().popBackStack();
}
}
return true;
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"> <Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="oneClick"
android:text="one" /> <Button
android:id="@+id/button2"
android:layout_width="88dp"
android:layout_height="48dp"
android:onClick="twoClick"
android:text="two" /> <FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="72dp"> </FrameLayout>
</LinearLayout>
public class PopBackFragment extends Fragment {
private String title;
public PopBackFragment() {
super();
}
public PopBackFragment(String title) {
this.title = title;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frag_pop_back, null);
TextView textView = (TextView) view.findViewById(R.id.text);
textView.setText(title);
return view;
}
}
5.Fragment的传参方式:
public static Fragment newInstance(String arg) {
TitleFragment titleFragment1 = new TitleFragment();
Bundle bundle = new Bundle();
bundle.putString("info", arg);
titleFragment1.setArguments(bundle);
return titleFragment1;
}
例如:
public void twoClick(View view) {
//用构造方法传值,有问题,在横竖屏切换时数据会丢失,不建议使用
// PopBackFragment p1 = new PopBackFragment("two");
//建议使用
PopBackFragment p1 = PopBackFragment.getInstance("two");
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.content, p1);
//把当前fragment添加到Activity栈
ft.addToBackStack(null);
ft.commit();
}
PopBackFragment
/**
* Fragmen的传参方法
* @param title
* @return
*/
public static PopBackFragment getInstance(String title) {
PopBackFragment p = new PopBackFragment();
Bundle bundle = new Bundle();
bundle.putString("title", title);
p.setArguments(bundle);
return p;
} @Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frag_pop_back, null);
TextView textView = (TextView) view.findViewById(R.id.text);
textView.setText(getArguments().getString("title"));
return view;
}
Fragment与Activity交互
fragment可以通过getActivity()函数访问Activity,并且很容易的执行类似于查找activity布局中的视图任务:
View listView = getActivity().findViewById(R.id.list);
activity能够调用fragment的函数findFragmentById()或者findFragmentByTag(),从FragmentManager中获取Fragment
TitleFragment fragment = (TitleFragment) getFragmentManager().findFragmentById(R.id.fragTitle);
fragment与activity共享事件
一个好方法是fragment内部定义一个回调接口,并需要宿主activity实现它。
当activity通过接口接收到回调时,可以在必要时与布局中的其他fragment共享信息。
宿主Activity:
public class MainActivity extends Activity implements TitleFragment.TitleListener {
private TitleFragment titleFragment;
private ContentFragment contentFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
titleFragment = (TitleFragment) getFragmentManager().findFragmentById(R.id.fragTitle);
contentFragment = (ContentFragment) getFragmentManager().findFragmentById(R.id.fragContent);
}
@Override
public void changeValue(String value) {
contentFragment.change(value);
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"> <fragment
android:id="@+id/fragTitle"
android:name="com.wzh.pushdemo.fragment.TitleFragment"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1" /> <fragment
android:id="@+id/fragContent"
android:name="com.wzh.pushdemo.fragment.ContentFragment"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>
触发事件的frag
public class TitleFragment extends Fragment implements View.OnClickListener {
private TitleListener titleListener;
private Button btnTime;
private Button btnSpace;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
titleListener = (TitleListener) activity;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frag_title, container, false);
btnTime = (Button) view.findViewById(R.id.btnTime);
btnSpace = (Button) view.findViewById(R.id.btnSpace);
btnTime.setOnClickListener(this);
btnSpace.setOnClickListener(this);
return view;
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnTime:
titleListener.changeValue("时间");
break;
case R.id.btnSpace:
titleListener.changeValue("地点");
break;
}
}
//定义一个回调接口,宿主要实现这个接口
public static interface TitleListener {
public void changeValue(String value);
}
}
frag_title.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00ff00"
android:orientation="vertical"
android:padding="10dp"> <Button
android:id="@+id/btnTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="时间" /> <Button
android:id="@+id/btnSpace"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="地点" /> </LinearLayout>
要改变值的frag
public class ContentFragment extends Fragment {
private TextView tvValue;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frag_content, container, false);
tvValue = (TextView) view.findViewById(R.id.tvValue);
return view;
}
public void change(String value) {
tvValue.setText(value);
}
}
frag_content.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00ddff"
android:orientation="vertical"> <TextView
android:id="@+id/tvValue"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="30dp"
android:text="Hello" /> </LinearLayout>
6、PreferenceFragment
有时候,我们的程序需要提供一些选项功能,能让用户去定制化自己的是用风格。例如,允许用户是否自动保存登录信息,允许用户设定某个页面的刷新时间等等,我们可以使用PreferenceActivity基类去显示给用户一个选项设置的界面,在Android3.0或更高版本上,可以使用PreferenceFragment类去实现这个功能。
下面将展示如何常见和使用PreferenceFragment:
(1)在res文件夹下新疆一个xml文件夹,在xml文件夹下面新建一个文件:preference.xml
(2)在包路径下面新建一个类:Fragment继承PreferenceFragment
(3)从xml文件加载选项addPreferencesFromResource(R.xml.preferences);
7、Fragment懒加载
如果ViewPager的每个Fragment都会拉取网络数据加载,而Fragment默认是加载前两个界面的,这样有可能会出现网络丢包或者网络堵塞情况,所以事先懒加载就有必要了。
实现懒加载的重点是public void setUserVisibleHint(boolean isVisibleToUser)方法,这个方法会优先于onCreate()方法的,即在调用onCreate前,isVisibleToUser已经获取到了,isVisibleToUser为true时表示页面用户能看到,false时看不到,之后可以在用户能看到页面时进行数据加载,不提前进行加载就可以了
@Override
public void onStart() {
super.onStart();
Log.d("TAG", mTagName + " onStart()"); ... if(getUserVisibleHint()) {
pullData();
} }
Fragment以及懒加载的更多相关文章
- Android之Viewpager+Fragment实现懒加载
我们在做应用开发的时候,一个Activity里面可能会以viewpager(或其他容器)与多个Fragment来组合使用.而ViewPager默认会缓存三页数据,即:Viewpager每加载一个Fra ...
- Andriod开发技巧——Fragment的懒加载
我们在做应用开发的时候,一个Activity里面可能会以viewpager(或其他容器)与多个Fragment来组合使用,而如果每个 fragment都需要去加载数据,或从本地加载,或从网络加载,那么 ...
- Android ViewPager Fragment使用懒加载提升性能
Android ViewPager Fragment使用懒加载提升性能 Fragment在如今的Android开发中越来越普遍,但是当ViewPager结合Fragment时候,由于Androi ...
- Fragment的懒加载
我们在做应用开发的时候,一个Activity里面可能会以viewpager(或其他容器)与多个Fragment来组合使用,而如果每个fragment都需要去加载数据,或从本地加载,或从网络加载,那么在 ...
- 关于Fragment的懒加载问题
为了达到界面效果,我们有时需要使用到TabLayout+ViewPager的方式来布局界面,然而ViewPager的adapter总是默认把与当前可见的fragment相邻的两个fragment给加载 ...
- Android优化方案之--Fragment的懒加载实现
一.背景 在Android应用中,ViewPager是我们不可避免使用的一个控件,因为它可以使我们在占用较少空间的同时,增强内容的丰富性,同时以其内部流淌着Google的血液,所以它几乎成了每一个Ap ...
- android ViewPager+Fragment之懒加载
说说写这篇博客的背景吧,前两天去面试,问到一个问题说的是:比如我们首页,是有3个fragment构成的,并且要是实现作用可以滑,那么这个最好的选择就是ViewPager+fragment了,但是我们知 ...
- 【Android】Fragment懒加载和ViewPager的坑
效果 老规矩,先来看看效果 ANDROID和福利两个Fragment是设置的Fragment可见时加载数据,也就是懒加载.圆形的旋转加载图标只有一个,所以,如果当前Fragment正处于加载状态,在离 ...
- ViewPager Fragment 懒加载 可见 总结 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
随机推荐
- Java之JNDI注入
Java之JNDI注入 About JNDI 0x01 简介 JNDI(Java Naming and Directory Interface)是SUN公司提供的一种标准的Java命名系统接口,JND ...
- mybatis替换成mybatisplus后报错mybatisplus Invalid bound statement (not found):
项目原来是mybatis,之后由于生成代码不方便,觉得替换成mybatisplus,引入mybatisplus后,启动项目报错mybatisplus Invalid bound statement ( ...
- CMU Convex Optimization(凸优化)笔记1--凸集和凸函数
CMU凸优化笔记--凸集和凸函数 结束了一段时间的学习任务,于是打算做个总结.主要内容都是基于CMU的Ryan Tibshirani开设的Convex Optimization课程做的笔记.这里只摘了 ...
- 18.jvm调优工具及案例分析
目标: Jmap.Jstack.Jinfo详解 JvisualVm调优工具实战 JVM内存或CPU飙高如何定位 JState命令预估JVM运行情况 系统频繁Full GC导致系统卡顿实战调优 内存泄漏 ...
- node对象
global,node的全局对象;js在游览器中的全局对象为windows 在node环境中;输入global.consloe 输出: Console { log: [Function: bound ...
- 解决一个无聊的问题,如何处理Java用户在dos被收集信息时拷贝带换行符的文本信息造成的while的多次循环(java解决Scanner.next在接收用户输入时出现多个换行的形况)[解决方案一]
问题描述: 用户在dos窗口输入的时候(web项目不会出现这样的问题,所以这个问题日常碰不到),摁下回车时,Scanner对象的next()扫描用户输入的文本,后面就可以根据输入的字符串进行判断,并执 ...
- 力扣 - 剑指 Offer 52. 两个链表的第一个公共节点
题目 剑指 Offer 52. 两个链表的第一个公共节点 思路1(栈) 若两个链表相遇,则从它开始相遇的地方到链表末尾应该都是相同的,那么我们可以将两个链表分别放入两个栈中,然后依次循环比较两个栈顶的 ...
- [loj3313]序列
定义$C_{i}$表示令$i,i+1,i+2,...$的位置减1的操作,定义$I_{i}$表示令$i,i+2,i+4,...$的位置减1的操作 结论1:一定存在一种最优解使得$\forall i$不同 ...
- 程序员需要达到什么水平才能顺利拿到 20k 无压力?
程序员要拿到20k,应该达到什么水平? 1 熟悉增删改查技能,熟悉项目开发相关流程和技能. 2 能解决基本问题,分布式或比较深的问题,太难的不会不要紧,但常规的应该有项目经验. 3 简历好看些 ...
- springboot 配置多数据源实例代码(分包方式)
目录 1.数据库 2.pom与yml 2.1.pom中的依赖部分 2.2.yml数据库配置部分 3.数据源配置类 DataSourceConfig 3.1.DataSourceConfig1.java ...