文章目录

  • Fragment的静态注册
  • Fragment的动态注册
  • Fragment生命周期
  • Fragment的常用类和API
  • Fragment 回退栈
  • Fragment与Activity之间的通信
    • Activity传递数据到Fragment(不推荐)
    • Fragment传递数据到Activity

Fragment的静态注册

​ 什么是静态注册,fragment的静态注册就是Activity中的标签属性(activity_main.xml中的fragment标签)和定义的Fragment类在运行之前已经绑定,运行时不在发生变化。

步骤:

  1. 声明一个类继承自Fragment加载自定义的布局

    注:fragment存在于两个包中,如果导入的是android.app.fragment包,已过时,如下图,那么与fragment相关联的Activity类可以继承自Activity(或者子类,fragment事务方法有区别);如果导入的是v4包中的fragment,那么与fragment相关联的Activity类必须继承自FragmentActivity或者AppCompatActivity

  2. 将activity布局中的<fragment>标签与fragment类绑定

    <fragmentandroid:id="required"android:tag="not_requiredandroid:name="继承自Fragment的全限定类名"android:layout_height="..."android:layout_width="..."/>
    

    id属性和name属性必填,否则抛出

    Caused by: java.lang.IllegalArgumentException: Binary XML file line #8: Must specify unique android:id, android:tag, or have a parent with an id for null
    

完整示例:

首先声明了两个类分别继承自v4包下的Fragment,然后通过onCreateView方法将布局加载并返回,我的理解继承Fragment类的作用,是将一个布局转换为fragment,然后该类才能附在fragment标签上。加载的两个布局代码就贴一个吧。

fragment_title.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@android:color/white"><TextViewandroid:layout_width="match_parent"android:layout_height="60dp"android:gravity="center"android:text="我是一个title"android:textSize="25sp"android:background="#4444F0"/>
</RelativeLayout>
import android.support.v4.app.Fragment;public class FragmentTitle extends Fragment {@Nullable@Overridepublic View onCreateView(LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_title, container, false);return view;}
}import android.support.v4.app.Fragment;/***android.support.v4.app.Fragment*加载Fragment的Activity必须继承FragmentActivity,否则他不会认为这是一个Fragment*/
public class FragmentContent extends Fragment {@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_content, container, false);return view;}
}

FragmentActivity类

/*** 1) 静态加载Fragment* 使用V4包下的Fragment,Activity需要继承自FragmentActivity|或者FragmentActivity的子类(AppCompatActivity)*/
public class FragmentActivity extends android.support.v4.app.FragmentActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_fragment);}
}

通过activity布局中的<fragment>标签静态绑定,activity_fragment布局如下。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><!--在main_activity中注册fragment标签==注意:它不是一个控件,它是一个引用型的标签==--><fragmentandroid:id="@+id/left_frag"android:tag="frag_left"android:name="cn.wjx34t0701.fragment.FragmentTitle"android:layout_height="wrap_content"android:layout_width="match_parent"/><fragmentandroid:id="@+id/right_frag"android:tag="frag_right"android:layout_height="match_parent"android:layout_width="match_parent"android:name="cn.wjx34t0701.fragment.FragmentContent" />
</LinearLayout>

运行截图

Fragment的动态注册

​ 动态注册的Fragment可以灵活的向activity布局容器中添加或者删除,就像java多态的特性那样,根据程序逻辑所需,动态绑定。

步骤:

  1. 继承Fragment,和前面静态注册一样。
  2. 在Activity中调用getSupportFragmentManager()(v4包下)获得FragmentManager对象,然后通过fragmentManager.beginTransaction()获得FragmentTransaction,开启事务,动态的对Fragment进行管理。

示例:

Activity所在布局,主要是对布局进行了简单的修改,通过<include>标签引入一个简单的底部导航栏,导航栏布局代码不在展示,就四个控件;然后借助framelayout控件承载我们的fragment。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><!--静态加载--><fragmentandroid:id="@+id/frag_title"android:layout_width="match_parent"android:layout_height="45dp"android:layout_alignParentTop="true"android:name="cn.wjx34t0701.fragment.FragmentTitle"/><!--动态加载fragment将其放入FrameLayout布局容器--><FrameLayoutandroid:id="@+id/frame_content"android:layout_below="@id/frag_title"android:layout_above="@id/bottombar"android:layout_width="match_parent"android:layout_height="match_parent"/><includeandroid:id="@+id/bottombar"layout="@layout/bottom_bar"android:layout_width="match_parent"android:layout_height="50dp"android:layout_alignParentStart="true"android:layout_alignParentBottom="true" /></RelativeLayout>

activity所在类,因为使用的是v4包下的fragment,所以这里继承的是AppCompatActivity

public class DynamicFragmentActivity extends AppCompatActivity implements View.OnClickListener {private TextView mTabWechat;private TextView mTabFriend;private WechatContent mWechatFragment;private FriendContent mFriendFragment;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_dynamic_fragment);initView();// 设置初始化fragmentsetDefaultFragment();}private void initView() {mTabWechat = findViewById(R.id.tab_wechat);mTabFriend = findViewById(R.id.tab_friend);mTabWechat.setOnClickListener(this);mTabFriend.setOnClickListener(this);}private void setDefaultFragment() {// 获取Fragment的管理对象 FragmentManager:用来在Fragment和Activity之间交互的接口FragmentManager fragmentManager = getSupportFragmentManager();// 获得事务对象,add、remove、replace等等操作都称为事务FragmentTransaction transaction = fragmentManager.beginTransaction();mWechatFragment = new WechatContent();transaction.replace(R.id.frame_content, mWechatFragment);/*** 其他常用事务* transaction.remove(Fragment);* transaction.hide(Fragment);* transaction.show(Fragment);*/// 提交事务transaction.commit();}@Overridepublic void onClick(View v) {FragmentManager fragmentManager = getSupportFragmentManager();// 开启fragment事务FragmentTransaction transaction = fragmentManager.beginTransaction();switch (v.getId()) {case R.id.tab_wechat:if (mWechatFragment == null) {mWechatFragment = new WechatContent();}transaction.replace(R.id.frame_content, mWechatFragment);break;case R.id.tab_friend:if (mFriendFragment == null) {mFriendFragment = new FriendContent();}transaction.replace(R.id.frame_content, mFriendFragment);break;}// 提交事务transaction.commit();}
}

还有两个Fragment,分别是WechatFragment和FriendFragment,这里偷了个巧,两者都使用了一个布局,主要是在onCreateView布局获取到的时候,对其中的控件做了一些改变。

public class WechatContent extends Fragment {@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_content, container, false);TextView textView = view.findViewById(R.id.content_tag);textView.setText("WeChat");return view;}
}public class FriendContent extends Fragment {public static final String TAG = "FriendContent";@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {Log.d(TAG, "onCreateView...");View view = inflater.inflate(R.layout.fragment_content, container, false);TextView textView = view.findViewById(R.id.content_tag);textView.setText("Friend Content");return view;}
}

Fragment生命周期

Fragment依存于Activity而存在,因此Activity的生命周期会直接影响到Fragment。

onAttach(Activity)
当Fragment与Activity发生关联时调用。
onCreateView(LayoutInflater, ViewGroup,Bundle)
创建该Fragment的视图
onActivityCreated(Bundle)
当Activity的onCreate方法返回时调用
onDestoryView()
与onCreateView想对应,当该Fragment的视图被移除时调用
onDetach()
与onAttach相对应,当Fragment与Activity关联被取消时调用
注意:除了onCreateView,其他的所有方法如果你重写了,必须调用父类对于该方法的实现,

Fragment的常用类和API

Fragment常用的三个类:

android.app.Fragment 主要用于定义Fragment

android.app.FragmentManager 主要用于在Activity中操作Fragment

android.app.FragmentTransaction 保证一些列Fragment操作的原子性,就像数据库中的事务一样。

  1. FragmentManager

    在activity所在类通过getSupportFragmentManager()或者getFragmentManager()(分别对应v4包和老包)获取

  2. FragmentTransaction 主要方法

    1. FragmentTransaction transaction = fm.benginTransatcion();开启一个事务

    2. transaction.add()

      往Activity中添加一个fragment

    3. transaction.remove()

      从Activity中移除一个Fragment,如果移除的Fragment没有添加到回退栈,这个Fragment实例将会被销毁

    4. transaction.replace()

      使用另一个Fragment替换当前的,实际上是remove()然后add()的结合

    5. transaction.hide()

      隐藏当前的Fragment,仅仅是设为不可见,并不会销毁

    6. transaction.show()

      显示之前隐藏的Fragment

    7. detach()

      会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护

    8. attach()

      重建view视图,附加到UI上并显示

    9. commit()

      提交一个事务

      Transaction主要方法 作用
      add() 往Activity中添加一个fragment
      remove() 从Activity中移除一个Fragment,如果移除的Fragment没有添加到回退栈,这个Fragment实例将会被销毁
      replace() 使用另一个Fragment替换当前的,实际上是remove()然后add()的结合
      hide() 隐藏当前的Fragment,仅仅是设为不可见,并不会销毁
      show() 显示之前隐藏的Fragment
      detach() 会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护
      attach() 重建view视图,附加到UI上并显示
      commit() 提交一个事务
      addToBackStack(“fname”) FragmentManager拥有回退栈(BackStack),类似于Activity的任务栈,如果添加了该语句,就把该事务加入回退栈,当用户点击返回按钮,会回退该事务(回退指的是如果事务是add(frag1),那么回退操作就是remove(frag1));如果没添加该语句,用户点击返回按钮会直接销毁Activity。

如何使用?

a、比如:我在FragmentA中的EditText填了一些数据,当切换到FragmentB时,如果希望会到A还能看到数据,则适合你的就是hide和show;也就是说,希望保留用户操作的面板,你可以使用hide和show,当然了不要使劲在那new实例,进行下非null判断。

b、再比如:我不希望保留用户操作,你可以使用remove(),然后add();或者使用replace()这个和remove,add是相同的效果。

c、remove和detach有一点细微的区别,在不考虑回退栈的情况下,remove会销毁整个Fragment实例,而detach则只是销毁其视图结构,实例并不会被销毁。那么二者怎么取舍使用呢?如果你的当前Activity一直存在,那么在不希望保留用户操作的时候,你可以优先使用detach。

Fragment 回退栈

类似与Android系统为Activity维护一个任务栈,我们也可以通过Activity维护一个回退栈来保存每次Fragment事务发生的变化。默认情况下,Fragment事务是不会加入回退栈的,如果你想将Fragment任务添加到回退栈,可以通过addToBackStack("")方法,当用户点击后退按钮时,将看到上一次的保存的Fragment。一旦Fragment完全从后退栈中弹出,用户再次点击后退键,则退出当前Activity。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WbONgAKY-1593345355851)(D:\FILE\NeHcIxbp2r.gif)]

MainActivity.java

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);FragmentManager fragmentManager = getSupportFragmentManager();FragmentTransaction transaction = fragmentManager.beginTransaction();transaction.add(R.id.frame_container, new FragmentOne(), "ONE");transaction.commit();}
}

activity布局代码很简单就不在贴了,就是将fragment放入framlayout中。

FragmentOne.java

public class FragmentOne extends Fragment implements View.OnClickListener {@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {// attachToRoot false,若为true会导致重复添加View view = inflater.inflate(R.layout.fragment_one, container, false);Button btTwo = view.findViewById(R.id.go_two);btTwo.setOnClickListener(this);return view;}@Overridepublic void onClick(View v) {FragmentTwo fmTwo = new FragmentTwo();FragmentManager fragmentManager = getFragmentManager();FragmentTransaction transaction = fragmentManager.beginTransaction();transaction.replace(R.id.frame_container, fmTwo, "TWO");transaction.addToBackStack(null);transaction.commit();}
}

点击FragmentOne中的按钮时,使用了replace方法,replace是remove和add的结合,并且如果不添加事务到回退栈,前一个Fragment实例会被销毁。这里很明显,我们调用tx.addToBackStack(null);将当前的事务添加到了回退栈,所以FragmentOne实例不会被销毁,~~但是视图层次依然会被销毁,即会调用onDestoryView和onCreateView,证据就是:仔细看上面的效果图,我们在跳转前在文本框输入的内容,在用户Back得到第一个界面的时候不见了。~~有歧义待研究,因为上面gif演示了视图层中的数据也还在

FragmentTwo.java

public class FragmentTwo extends Fragment implements View.OnClickListener {public static final String TAG = "FragmentTwo";@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {// attachToRoot false,若为true会导致重复添加View view = inflater.inflate(R.layout.fragment_two, container, false);Button btTwo = view.findViewById(R.id.go_three);btTwo.setOnClickListener(this);return view;}@Overridepublic void onClick(View v) {FragmentThree fmThree = new FragmentThree();FragmentManager fragmentManager = getFragmentManager();FragmentTransaction transaction = fragmentManager.beginTransaction();transaction.hide(this);transaction.add(R.id.frame_container, fmThree);// transaction.replace(R.id.frame_container, fmThree, "THREE");transaction.addToBackStack(null);transaction.commit();}

这里点击时,我们没有使用replace,而是先隐藏了当前的Fragment,然后添加了FragmentThree的实例,最后将事务添加到回退栈。这样做的目的是为了给大家提供一种方案:如果不希望视图重绘该怎么做,请再次仔细看效果图,我们在FragmentTwo的EditText填写的内容,用户Back回来时,数据还在【当做一种技巧吧!】

Fragment与Activity之间的通信

Activity传递数据到Fragment(不推荐)

  1. 在将fragment添加到事务之前设置fragment.setArguments(Bundle);

    //举例
    //Activity中
    Fragment fm = new Fragment();
    Bundle bundle = new Bundle();
    bundle.putString("hello", hello);
    fm.setArguments(bundle);//Fragment中
    Bundle bundle = getArguments();
    //获取bundle之后,再用bundle获取对应的数据
    String hello = bundle.getString("hello");
    
  2. 使用findFragmentByTag()方法获取Fragment,调用Fragment的方法。(注:动态添加fragment的同时 设置标签调用transaction.add(container, fragment, TAG);,当fragment动态加入的时候,才可以findFragmentByTag)

     //获取当前页面的fragment,这里的Tag是在将Fragment添加到布局的时候设置的。
    Fragment fragment = (Fragment) getSupportFragmentManager().findFragmentByTag(tag);
    //调用相应的方法
    fragment.xxx();
    // 比如,我可以获取TAG为"one"的fragment然后根据类型做一定的强转,调用方法进行通信
    Fragment one = getFragmentManager().findFragmentByTag("one");
    if (one instanceof FragmentOne) {((FragmentOne) one).sayHell();
    }
    

Fragment传递数据到Activity

因为要考虑Fragment的重复使用,所以必须降低Fragment与Activity的耦合,而且Fragment更不应该直接操作别的Fragment,毕竟Fragment操作应该由它的管理者Activity来决定。

下面以Activity响应FragmentOne和FragmentTwo中点击事件为例进行讲解。

FragmentOne.java

public class FragmentOne extends Fragment implements View.OnClickListener {public static final String TAG = "FragmentOne";public interface FOneBtnClickListener {void onFOneBtnClick(String msg);}@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {Bundle arguments = getArguments();if (arguments != null) {Log.d(TAG, "arguments "+arguments.get("content"));}// attachToRoot false,若为true会导致重复添加View view = inflater.inflate(R.layout.fragment_one, container, false);Button btTwo = view.findViewById(R.id.go_two);btTwo.setOnClickListener(this);return view;}@Overridepublic void onClick(View v) {if (getActivity() instanceof MainActivity) {((MainActivity) getActivity()).onFOneBtnClick("fragment_one send a msg");}}
}

FragmentOne不与任何Activity耦合,为什么?因为接口,当FragmentOne点击事件发生后,会进行判断当前Activity是否实现了该接口,如果实现了那么就会回调到Activity所在类,这是一种通信的方式,否则不会回调。

FragmentTwo.java

public class FragmentTwo extends Fragment implements View.OnClickListener {public static final String TAG = "FragmentTwo";private FTwoBtnClickListener mListener;public interface FTwoBtnClickListener {void onFTwoBtnClick(String msg);}public void setListener(FTwoBtnClickListener listener) {mListener = listener;}@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {// attachToRoot false,若为true会导致重复添加View view = inflater.inflate(R.layout.fragment_two, container, false);Button btTwo = view.findViewById(R.id.go_three);btTwo.setOnClickListener(this);return view;}@Overridepublic void onClick(View v) {if (mListener != null) {mListener.onFTwoBtnClick("fragment_two send a msg");}}
}

与FragmentOne极其类似,但是我们提供了setListener这样的方法,意味着Activity不仅需要实现该接口,还必须显示调用mFTwo.setfTwoBtnClickListener(this)。

public class MainActivity extends AppCompatActivity implements FragmentOne.FOneBtnClickListener, FragmentTwo.FTwoBtnClickListener {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Bundle bundle = new Bundle();bundle.putCharSequence("content", "activity send a msg");FragmentOne fragmentOne = new FragmentOne();FragmentManager fragmentManager = getSupportFragmentManager();FragmentTransaction transaction = fragmentManager.beginTransaction();fragmentOne.setArguments(bundle);transaction.add(R.id.frame_container, fragmentOne, "ONE");transaction.commit();}/*** FragmentOne 按钮点击时的回调*/@Overridepublic void onFOneBtnClick(String msg) {Toast.makeText(this, "msg-->"+msg, Toast.LENGTH_SHORT).show();FragmentManager fragmentManager = getSupportFragmentManager();FragmentTwo fmTwo = new FragmentTwo();fmTwo.setListener(this);FragmentTransaction transaction = fragmentManager.beginTransaction();transaction.replace(R.id.frame_container, fmTwo, "TWO");transaction.addToBackStack(null);transaction.commit();}@Overridepublic void onFTwoBtnClick(String msg) {Toast.makeText(this, "msg-->"+msg, Toast.LENGTH_SHORT).show();}
}

上面两种通信方式都是值得推荐的,随便选择一种自己喜欢的。这里再提一下:虽然Fragment和Activity可以通过getActivity与findFragmentByTag或者findFragmentById,进行任何操作,甚至在Fragment里面操作另外的Fragment,但是没有特殊理由是绝对不提倡的。**Activity担任的是Fragment间类似总线一样的角色,应当由它决定Fragment如何操作。**另外虽然Fragment不能响应Intent打开,但是Activity可以,Activity可以接收Intent,然后根据参数判断显示哪个Fragment。

参考

郭霖Android Fragment 真正的完全解析

《Android Fragment 非常详细的一篇》

上手Fragment相关推荐

  1. android组件浮动在activity上_Jetpack Hilt 依赖注入框架上手指南

    code小生 一个专注大前端领域的技术平台公众号回复Android加入安卓技术群 作者:LvKang-insist 链接:https://juejin.im/post/5efdff9d6fb9a07e ...

  2. Vue简单快速上手 idea版

    文章目录 版本 插件安装和通过CDN使用Vue Vue的基本语法 v-bind 条件判断 循环 监听事件 表单双绑 1.什么是双向数据绑定 2.在表单中使用双向数据绑定 组件 什么是组件 第一个Vue ...

  3. Playcanvas 上手使用

    整体使用上与Unity 比较像,上手比较快 zTutorials | Learn PlayCanvas entity =>对应GameObject asset 磁盘上为加载的资源 ScriptA ...

  4. 在Web 3D 游戏开发的前端如何快速上手进行

    本文以「余额宝3D跑酷游戏」为例,介绍了前端如何快速上手 Web 3D 游戏的开发.跑酷游戏是余额宝七周年的主玩法,用户通过做任务来获取玩游戏的机会并且解锁游戏道具,从而在游戏中获得更多的金币,最终可 ...

  5. Vue2简单使用及相关基础知识概念(适合小白入门,看完就能上手)

    Vue2相关知识 一.概念 1.前端模式 2.MVVM模式 2.1 概念 2.2 优点 (1)低耦合 (2)可复用 (3)独立开发 (4)可测试 3.Vue 3.1 概念 3.2 优点 3.3 参考网 ...

  6. 适合初学者入门的项目,通过对 Kotlin 的系统运用,实现的一个功能完备符合主流市场标准 App。包含知识点(MVVM 开发架构、单 Activity 多 Fragment 项目设计、暗夜模式、屏幕

    fragmject 项目地址:miaowmiaow/fragmject 简介: 适合初学者入门的项目,通过对 Kotlin 的系统运用,实现的一个功能完备符合主流市场标准 App.包含知识点(MVVM ...

  7. 【快速上手mac必备】常用优质mac软件推荐(音视频、办公、软件开发、辅助工具、系统管理、云存储)

    本文章的主要内容是我作为一名大四学生.准程序员.up主这三种身份来给大家推荐一下 mac 上好用的软件以及工具.本人也是从去年9月份开始从windows阵营转移到了mac阵营,刚开始使用的时候,也曾主 ...

  8. 狂神Spring Boot 员工管理系统 超详细完整实现教程(小白轻松上手~)

    [SpringBoot-web系列]前文: SpringBoot-web开发(一): 静态资源的导入(源码分析) SpringBoot-web开发(二): 页面和图标定制(源码分析) SpringBo ...

  9. Fragment之间传递数据的方式

    1.直接调用另一个Fragent对象的方法,两个Fragment之间高度耦合 2.采取接口回调的方式进行数据传递.即在一个fragment中创建一接口以及接口对应的set方法,在另一个fagment中 ...

最新文章

  1. libevent mysql_在 libevent 中使用 MariaDB(MySQL)
  2. 使用JProfiler查看GC Roots
  3. [C/C++基础知识] 一篇就让你彻底搞懂qsort快速排序的文章
  4. 硬币 假硬币 天平_小东西叫硬币
  5. JAVA入门级教学之(异常的处理try...catch)
  6. 《0bug-C/C++商用工程之道》节选00--内存管理的基本要求
  7. ospf的七类lsa存在于_OSPF抑制7类LSA的转发
  8. mysql重置root密码centos_Centos7重置Mysql 8.0.1 root 密码
  9. 金融现金贷用户数据分析和用户画像
  10. Android代码中获取Drawable对象
  11. 学习沟通技巧--- SOFTEN法则与SOLER法则
  12. 五星大饭店续集剧情大放送(最新更新)
  13. 磁盘碎片对计算机系统的影响,磁盘碎片整理第9遍了|Win7磁盘碎片整理的方法
  14. 联网获取360数据,识别骚扰电话,java实现
  15. ❤️Java中经纬度换算❤️
  16. 用生物知识解读“新冠病毒”,生物竞赛、高考考点,先马后看!
  17. C/C++ 余弦函数 cos - C语言零基础入门教程
  18. 程序员不愁没练手的小项目
  19. 孙浩北大计算机,周耀山工作简报第53期——清华北大高材生黎明、孙浩在白河高级中学学法座谈会成功举行...
  20. 2020年司钻(井下)考试题库及司钻(井下)考试APP

热门文章

  1. 蚂蚁笔记 linux安装教程,群晖docker安装蚂蚁笔记安装教程
  2. 思维导图工具之Mindmeister
  3. Debian 7.4 下mentohust开机自动认证
  4. 长沙航空职业技术学院计算机系,长沙航空职业技术学院机器人专业怎么样
  5. Aziz 的 UiPath 工具面试经验
  6. 小学生python趣味编程-Python少儿趣味编程
  7. vs2022 c#调用interop.word 12.0版本也就是word2007实现首行缩进两个字符
  8. 2020豆瓣电影首页热门电影+热门电视剧 API
  9. linux who 时间,linux命令之who、w、whoami
  10. 内存大计算机运行就快吗,提高电脑内存的运行速度的方法你会吗