代码改变世界

深入解析:Android Studio新手开发第二十四天

2025-11-19 22:42  tlnshuju  阅读(0)  评论(0)    收藏  举报

目录

碎片Fragment

碎片的静态注册

碎片的动态注册

碎片Fragment

        Fragment(碎片)是 Android 中非常重要的组件,它代表 Activity 中的一部分行为或用户界面。它有自己的生命周期,但受宿主 Activity 影响而且能够被多个Activity重复使用。每个碎片都有对应的xml布局文件,它有两种使用方式:静态注册以及动态注册,两者的对比如下表所示。

静态注册动态注册
定义方式XML布局文件中使用<fragment>标签声明Java/Kotlin代码中使用FragmentTransaction操作
传参方式困难。无法在布局中直接传递参数方便。可通过BundlesetArguments()方法传递参数
适用场景界面固定不变的通用UI部件(如公共头部、底部)界面需要动态变化的情况(如标签页、ViewPager)
灵活性。布局固定,难以在运行时替换。可在运行时灵活地添加、移除、替换碎片

碎片的静态注册

        静态注册是指在xml文件中直接添加Fragment节点,可以看做是一个普通的控件能够被多个布局文件重复使用。该注册方式多用于界面固定不变的场景如广告条等,每个活动页面均可直接使用该部件。碎片除了与活动页面一样的基本生命周期方法onCreate、onStart、onStop、onResume、onPause、onDestroy之外还有五个生命周期方法,说明如下:

        onAttach:与活动页面结合。

        onCreateView:创建碎片视图。

        onActivityCreated:在活动页面创建完毕后调用。

        onDestroyView:回收碎片视图。

        onDetach:与活动页面分离。

        下面将展示静态注册的示例代码以及碎片生命周期。先右键依次选择New、Fragment新建一个Fragment,然后重写上述方法。

        碎片的布局文件代码如下。



    
    
    

        碎片的部分Java代码如下。

    private final String TAG = "StaticRegisterFragment";
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
        Log.d(TAG, "onCreate");
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView");
        return inflater.inflate(R.layout.fragment_static_register, container, false);
    }
    @Override
    public void onAttach(@NonNull Context context) {
        Log.d(TAG, "onAttach");
        super.onAttach(context);
    }
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        Log.d(TAG, "onViewCreated");
        super.onViewCreated(view, savedInstanceState);
    }
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.d(TAG, "onActivityCreated");
    }
    @Override
    public void onStart() {
        super.onStart();
        Log.d(TAG, "onStart");
    }
    @Override
    public void onResume() {
        super.onResume();
        Log.d(TAG, "onResume");
    }
    @Override
    public void onPause() {
        super.onPause();
        Log.d(TAG, "onPause");
    }
    @Override
    public void onStop() {
        super.onStop();
        Log.d(TAG, "onStop");
    }
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.d(TAG, "onDestroyView");
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }
    @Override
    public void onDetach() {
        super.onDetach();
        Log.d(TAG, "onDetach");
    }

        页面布局文件代码如下,其中Fragment节点必须要有id以及Name的值为指定碎片的完整路径。



    

        页面部分Java代码如下。

public class FragmentActivity extends AppCompatActivity {
    private final String TAG = "FragmentActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment);
        Button button = findViewById(R.id.button_fragment);
        TextView textView = findViewById(R.id.textView_fragment);
        button.setOnClickListener(view -> {
            Toast.makeText(FragmentActivity.this, "点击了碎片中的按钮!", Toast.LENGTH_SHORT).show();
            textView.setText("点击了碎片中的按钮!");
            imageView.setImageResource(R.drawable.image_2);
        });
        Log.d(TAG, "onCreate");
    }
    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "onStart");
    }
    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "onStop");
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }
    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause");
    }
    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume");
    }
}

效果图如下,可以看到碎片能够正确显示,而且能够在页面的Java代码中获取碎片中的视图实例并做出操作,如给按钮添加监听器,修改文本视图的文本内容,更改图片视图的图片。

        在Android Studio下方的Logcat能够看到碎片已经活动页面的部分生命周期。可以看到先加载碎片在加载这个页面。

碎片的动态注册

        动态注册是在代码执行时才动态添加碎片。动态生成的碎片一般是给翻页视图使用。之前讲过翻页视图的数据适配器是PagerAdapter,但如果要结合使用碎片就需要使用另一种适配器FragmentPagerAdapter碎片适配器。该适配器增加了一个方法getItem用于获取指定位置的碎片同时去掉了三个方法,分别为isViewFromObject、instantiateItem与destroyItem。示例代码如下。

        碎片的布局文件代码。



    
    
    

        碎片的Java部分代码,主要看构造函数以及方法onCreateView。

public class DynamicRegisterFragment extends Fragment {
    public DynamicRegisterFragment() {
        // Required empty public constructor
    }
    private Context mContext;
    private View mView;
    private int position;
    private int image_id;
    //    private int number;
    private String number_english;
    public static DynamicRegisterFragment newInstance(int position, int image_id, String number_english) {
        DynamicRegisterFragment fragment = new DynamicRegisterFragment();
        Bundle args = new Bundle();
        args.putInt("position", position);
        args.putInt("image_id", image_id);
        args.putString("number_english", number_english);
        fragment.setArguments(args);
        return fragment;
    }
    private final String TAG = "DynamicRegisterFragment";
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate");
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView");
        mContext = getActivity();
        if(getArguments() != null){
            image_id = getArguments().getInt("image_id");
            position = getArguments().getInt("position");
            number_english = getArguments().getString("number_english");
        }
        mView = inflater.inflate(R.layout.fragment_dynamic_register,container,false);
        ImageView imageView = mView.findViewById(R.id.imageView_fragment);
        TextView textView = mView.findViewById(R.id.textView_fragment);
        Button button = mView.findViewById(R.id.button_fragment);
        imageView.setImageResource(image_id);
        textView.setText(number_english);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(mContext,String.format("点击了第%d个碎片中的按钮!",position+1),Toast.LENGTH_SHORT).show();
            }
        });
        return mView;
    }
    @Override
    public void onAttach(@NonNull Context context) {
        Log.d(TAG, "onAttach");
        super.onAttach(context);
    }
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        Log.d(TAG, "onViewCreated");
        super.onViewCreated(view, savedInstanceState);
    }
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.d(TAG, "onActivityCreated");
    }
    @Override
    public void onStart() {
        super.onStart();
        Log.d(TAG, "onStart");
    }
    @Override
    public void onResume() {
        super.onResume();
        Log.d(TAG, "onResume");
    }
    @Override
    public void onPause() {
        super.onPause();
        Log.d(TAG, "onPause");
    }
    @Override
    public void onStop() {
        super.onStop();
        Log.d(TAG, "onStop");
    }
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.d(TAG, "onDestroyView");
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }
    @Override
    public void onDetach() {
        super.onDetach();
        Log.d(TAG, "onDetach");
    }
}

        页面布局文件代码如下。



    
        
    

        页面的部分Java代码如下,主要看碎片适配器的内容。        

public class FragmentActivity extends AppCompatActivity {
    private final String TAG = "FragmentActivity";
    private int[] image_id = {R.drawable.one, R.drawable.two, R.drawable.three, R.drawable.four, R.drawable.five,
            R.drawable.six, R.drawable.seven, R.drawable.eight, R.drawable.nine, R.drawable.zero};
    private Integer[] number = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    private String[] number_english = {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "zero"};
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment);
        MyFragmentPagerAdapter myFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager(),this,getList());
        ViewPager viewPager = findViewById(R.id.viewPager);
        viewPager.setAdapter(myFragmentPagerAdapter);
        viewPager.setCurrentItem(1);
        Log.d(TAG, "onCreate");
    }
    public List getList() {
        List numberInfoList = new ArrayList();
        for (int i = 0; i < number.length; i++) {
            NumberInfo numberInfo = new NumberInfo(image_id[i],number[i],number_english[i]);
            numberInfoList.add(numberInfo);
        }
        return numberInfoList;
    }
    class NumberInfo {
        private int image_id;
        private int number;
        private String number_english;
        public NumberInfo(int image_id,int number,String number_english){
            this.image_id = image_id;
            this.number = number;
            this.number_english = number_english;
        }
    }
    class MyFragmentPagerAdapter extends FragmentPagerAdapter{
        private List numberInfoList;
        private Context mContext;
        public MyFragmentPagerAdapter(FragmentManager fragmentManager, Context context, List numberInfoList){
            super(fragmentManager,BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
            this.mContext = context;
            this.numberInfoList = numberInfoList;
        }
        @Nullable
        @Override
        public CharSequence getPageTitle(int position) {
            return numberInfoList.get(position).number_english;
        }
        @NonNull
        @Override
        public Fragment getItem(int position) {
            return DynamicRegisterFragment.newInstance(position,numberInfoList.get(position).image_id,numberInfoList.get(position).number_english);
        }
        @Override
        public int getCount() {
            return numberInfoList.size();
        }
    }
    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "onStart");
    }
    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "onStop");
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }
    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause");
    }
    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume");
    }
}

        效果图如下,点击按钮有所反应。

        动态注册碎片的生命周期如下。无论当前位于哪一页,系统只会加载当前页面以及左右两页,最多加载三页。这种方式可以节省系统资源,减少浪费,这是普通翻页视图所没有的。