四大组件----Activity(二)----fragment

一.创建Fragment

Fragment lifecycle.png

1.一般情况下,你至少需要实现以下几个生命周期方法:

onCreate()

在创建fragment时系统会调用此方法。在实现代码中,你可以初始化想要在fragment中保持的那些必要组件,当fragment处于暂停或者停止状态之后可重新启用它们。

onCreateView()

在第一次为fragment绘制用户界面时系统会调用此方法。为fragment绘制用户界面,这个函数必须要返回所绘出的fragment的根View。如果fragment没有用户界面可以返回空。

onPause()

系统回调用该函数作为用户离开fragment的第一个预兆(尽管这并不总意味着fragment被销毁)。在当前用户会话结束之前,通常要在这里提交任何应该持久化的变化(因为用户可能不再返回)。
2.添加用户界面

inflate()函数需要以下三个参数:

(1)要inflate的布局的资源ID。

(2)被inflate的布局的父ViewGroup。传入container很重要,这是为了让系统将布局参数应用到被inflate的布局的根view中去,由其将要嵌入的父view指定。

(3)一个布尔值,表明在inflate期间被infalte的布局是否应该附上ViewGroup(第二个参数)。

3.将fragment添加到activity之中

(1)在activity的布局中声明fragment

         <fragment>中的android:name 属性指定了布局中实例化的Fragment类

注意:每个fragment都需要一个唯一的标识,如果重启activity,系统可用来恢复fragment(并且可用来捕捉fragment的事务处理,例如移除)。为fragment提供ID有三种方法:

  • 用android:id属性提供一个唯一的标识。
  • 用android:tag属性提供一个唯一的字符串。
  • 如果上述两个属性都没有,系统会使用其容器视图(view)的ID。
(2)通过编码将fragment添加到已存在的viewgroup中
eg.     FragmentManager fragmentManager = getFragmentManager()
	FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        ExampleFragment fragment = new ExampleFragment();
	fragmentTransaction.add(R.id.fragment_container, fragment);
	fragmentTransaction.commit();
传入add()函数:第一个参数是fragment被放置的ViewGroup,它由资源ID(resource ID)指定,
               第二个参数就是要添加的fragment
4.添加无界面的fragment

        想要添加没有界面的fragment ,可以使用add(Fragment, String)(为fragment提供一个唯一的字符串“tag”,而不是视图(view)ID)。

        为无界面fragment提供字符串标签并不是专门针对无界面fragment的——也可以为有界面fragment提供字符串标签——但是对于无界面fragment,字符串标签是唯一识别它的方法。如果之后想从activity中取到fragment,需要使用findFragmentByTag()。


二.管理Fragments

通过getFragmentManager()获得的FragmentManager 可以做如下事情,包括:

  • 使用findFragmentById()(用于在activity布局中提供有界面的fragment)或者findFragmentByTag()获取activity中存在的fragment(用于有界面或者没有界面的fragment)。
  • 使用popBackStack()(模仿用户的BACK命令)从后台栈弹出fragment。
  • 使用addOnBackStackChangedListener()注册一个监听后台栈变化的监听器。
三.处理Fragment事务

1.将变更添加到FragmentTransaction中的顺序注意以下两点:

(1)必须要在最后调用commit()

(2)如果你正将多个fragment添加到同一个容器中,那么添加顺序决定了它们在视图层次里显示的顺序。

2.在执行删除fragment事务时,没有调用addToBackStack(),那么事务一提交fragment就会被销毁,而且用户也无法回退它。然而,当移除一个fragment时,调用了addToBackStack(),那么之后fragment会被停止,如果用户回退,它将被恢复过来。

提示:对于每一个fragment事务,在提交之前通过调用setTransition()来应用一系列事务动作。

3.调用commit()并不立刻执行事务,相反,而是采取预约方式,一旦activity的界面线程(主线程)准备好便可运行起来。然而,如果有必要的话,你可以从界面线程调用executePendingTransations()立即执行由commit()提交的事务。但这样做,通常是没有必要的,除非其它线程的工作依赖于该项事务。

警告:只能在activity保存状态(当用户离开activity时)之前用commit()提交事务。如果你尝试在那时之后提交,会抛出一个异常。这是因为如果activity需要被恢复,提交后的状态会被丢失。对于这类丢失提交的情况,可使用commitAllowingStateLoss()

四.与activity交互

***fragment可以通过getActivity()函数访问Activity

  eg.View listView = getActivity().findViewById(R.id.list);
***activity能够调用fragment的函数findFragmentById()或者findFragmentByTag()
  eg.ExampleFragment fragment = (ExampleFragment) getFragmentManager()
                               .findFragmentById(R.id.example_fragment);
1.创建activity事件回调函数

        在一些情况下,你可能需要fragment与activity共享事件。这样做的一个好方法是在fragment内部定义一个回调接口,并需要宿主activity实现它。当activity通过接口接收到回调时,可以在必要时与布局中的其它fragment共享信息。为了确保宿主activity实现了这个接口,fragment的onAttach()回调函数(当添加fragment到activity中时系统会调用它)通过作为参数传入onAttach()的activity的类型转换来实例化一个在fragment里定义的接口(SampleListener)的实例。

@Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (SampleListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement SampleListener");
        }
    }
        如果activity没有实现这个接口,那么fragment会抛出一个ClassCaseException异常。一旦成功,mListener成员会保留一个activity的SampleListener实现的引用,由此fragment可以通过调用由SampleListener接口定义的方法与activity共享事件。

2.添加items到ActionBar

你的fragments可以通过实现onCreateOptionsMenu()来构建菜单项到activity的Options Menu(因此Action Bar也一样)。为了使用这个方法接收到调用,不管怎样,你必须在onCreate()期间调用setHasOptionsMenu(),来指明想要添加项目到Options Menu的那个fragment(否则,fragment将接收不到onCreateOptionsMenu()的调用)。

任何想要在fragment中的Options Menu添加的项目都追加到已有的菜单项后面。当菜单项被选中时,fragment也会接收到对onOptionsItemSelected()的回调。

你也可以通过调用registerForContextMenu()在fragment布局中注册一个view以提供一个context menu。当用户打开context menu时,fragment接收到对onCreateContextMenu()的回调。当用户选中一个项目时,fragment接收到对onContextItemSelected()的回调。

注意:尽管你的fragment会接收到为添加到每个菜单项被选择菜单项的回调,但当用户选择一个菜单项时,activity会首先接收到对应的回调。如果activity的选择菜单项回调的实现没有处理被选中的项目,那么该事件被传递给fragment的回调。这同样适用于Options Menu和context menu。

五.处理Fragment的生命周期

        同activity类似,你可以用Bundle保存fragment状态,万一activity的进程被杀掉了,并且在activity被重新创建时,你需要恢复fragment状态。在回调执行fragment的onSaveInstanceState()期间保存状态,在onCreate()或者onCreateView()或者onActvityCreate()中可以恢复状态。

1.与activity生命周期的协调合作

Fragment有一些额外的生命周期回调方法:

onAttach()
当fragment被绑定到activity时调用(Activity会被传入)。
onCreateView()
创建与fragment相关的视图体系时被调用。
onActivityCreated()
当activity的onCreate()函数返回时被调用。
onDestroyView()
当与fragment关联的视图体系正被移除时被调用。
onDetach()
当fragment正与activity解除关联时被调用。

        一旦activity处于resumed状态,则可以在activity中自由的添加或者移除fragment。因此,只有当activity处于resumed状态时,fragment的生命周期才可以独立变化。

2.例子:

主Activity布局--纵向的

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/fl_title"
        android:name="com.example.administrator.fragmentlearn.TitleFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></fragment>

</RelativeLayout>
主Activity布局--横向的
<?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/fl_title"
        android:name="com.example.administrator.fragmentlearn.TitleFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"></fragment>

    <FrameLayout
        android:id="@+id/fl_detail"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"></FrameLayout>
</LinearLayout>
TitleFragment.java

public class TitleFragment extends ListFragment {// 因为继承的是ListFragment,
                                         // 所以不用实现onCreateView()的方法,因为已经默认实现了
    public static String POSITION = "position";
    private String[] titles = {"标题一", "标题二", "标题三", "标题四", "标题五", "标题六"};
    private int curPosition = 0;// 当前选择的是第几个标题
    private boolean isPaint;

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setListAdapter(new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_activated_1, titles));

        if (savedInstanceState != null)
            curPosition = savedInstanceState.getInt(POSITION);

        View view = getActivity().findViewById(R.id.fl_detail);
        isPaint = view != null && view.getVisibility() == View.VISIBLE;
        if (isPaint) {
            getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
            showDetail();
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(POSITION, curPosition);
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        curPosition = position;
        showDetail();
    }

    private void showDetail() {
        if (isPaint) {
            getListView().setItemChecked(curPosition, true);
            DetailFragment fragment = (DetailFragment) getFragmentManager().findFragmentById(R.id.fl_detail);
            if (fragment == null || fragment.getShownPosition() != curPosition) {
                fragment = DetailFragment.newInstance(curPosition);
                getFragmentManager().beginTransaction().replace(R.id.fl_detail, fragment).commit();
            }
        } else {
            Intent intent = new Intent(getActivity(),DetailActivity.class);
            intent.putExtra(POSITION,curPosition);
            startActivity(intent);
        }
    }
}
DetailFragment.java

import static com.example.administrator.fragmentlearn.TitleFragment.POSITION;
public class DetailFragment extends Fragment {

    public static DetailFragment newInstance(int position) {
        DetailFragment fragment = new DetailFragment();
        Bundle args = new Bundle();
        args.putInt(POSITION, position);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if (container == null)// 防止不是横屏时调用此类
            return null;
        ScrollView scrollView = new ScrollView(getActivity());
        TextView textView = new TextView(getActivity());
        int padding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, getActivity().getResources().getDisplayMetrics());
        textView.setPadding(padding, padding, padding, padding);
        String content = getShownPosition() + "开始";
        for (int i = 0; i < 100; i++)
            content += "标题" + getShownPosition() + "下的内容";
        textView.setText(content);
        scrollView.addView(textView);
        return scrollView;
    }

    public int getShownPosition() {
        return getArguments().getInt(POSITION);
    }

}
DetailActivity.java

import static com.example.administrator.fragmentlearn.TitleFragment.POSITION;
public class DetailActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
            finish();
            return;// 防止横向时调用此类(竖屏进入到详情后,再横屏会发生)
        }
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction().add(android.R.id.content, DetailFragment.newInstance(getIntent().getIntExtra(POSITION, 0))).commit();
        }
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值