掌握Android Fragment开发之魂:Fragment的深度解析(上)

news2024/11/24 19:11:20

Fragment是Android开发中用于构建动态和灵活界面的基石。它不仅提升了应用的模块化程度,还增强了用户界面的动态性和交互性,允许开发者将应用界面划分为多个独立、可重用的部分,每个部分都可以独立于其他部分进行操作。本文将从以下几个方面深入探讨Fragment的核心特性、优势、生命周期,以及如何通过静态和动态添加来丰富你的应用。


一、Fragment的特点


Fragment是Android中非常强大和灵活的概念,它极大地简化了构建动态和可适应不同屏幕尺寸的复杂UI的过程。通过合理利用Fragment,您可以构建模块化、可重用和高效的Android应用程序。


以下是Fragment的一些主要特点:

  1. 模块化UI: Fragment允许您将UI分解为独立的模块化组件。每个Fragment都定义了自己的布局和行为,并且可以在活动中添加、删除或替换。这使得构建可重用的UI组件和适应不同屏幕尺寸变得更加容易。

  2. 生命周期管理: 与Activity类似,Fragment也有自己的生命周期。系统负责管理Fragment的生命周期,使您能够专注于编写代码而不必担心生命周期问题。Fragment的生命周期回调与Activity的生命周期回调类似,但Fragment的生命周期优先于托管它的Activity。

  3. 向后兼容性: 在旧版本的Android系统上,Fragment提供了一种模拟新UI模式的方法。即使在较旧的Android版本上,您也可以编写支持片段的应用程序。

  4. 动态UI: Fragment可以在运行时动态添加到Activity布局中。这为您提供了灵活性,可以根据不同的条件动态构建和改变UI。

  5. 嵌套Fragment: Fragment可以嵌套在另一个Fragment中,这为构建复杂的UI层次结构提供了极大的灵活性。

  6. 支持多窗格设计: Fragment非常适合在大屏幕设备(如平板电脑)上实现多窗格UI设计。您可以将不同的Fragment组合在一个Activity中,并根据设备方向和大小调整布局。

  7. 提高可重用性: Fragment可以在多个Activity之间共享和重用。这不仅提高了代码的可重用性,还减少了代码重复,从而提高了应用程序的可维护性。

  8. Fragment事务: Fragment事务允许您在Activity布局中添加、移除、替换和附加Fragment。您可以通过提交一系列Fragment事务来构建复杂的UI流程。

  9. 支持RetainInstance: Fragment可以在配置更改(如设备旋转)时保留其实例。这意味着您可以避免重新创建昂贵的对象,从而提高应用程序的性能和响应能力。

  10. 向后兼容库支持: Android提供了对旧版本系统的Fragment向后兼容库支持。即使在较旧的Android版本上,您也可以使用Fragment提供的大多数功能。


二、Fragment的生命周期

在这里插入图片描述


Fragment的生命周期与Activity紧密相关,但有自己的特点。了解Fragment的生命周期对于正确管理Fragment至关重要。

Android Fragment拥有自己的生命周期,类似于Activity的生命周期。Fragment的生命周期回调方法与Activity非常相似,但又有一些独特之处。下面是Fragment生命周期的详细介绍,并通过Java代码示例进行演示:


1、onAttach(Context)

当Fragment与Activity实例关联时调用。可以在此方法中获取Activity的引用,并执行一些初始化操作。

@Override
public void onAttach(@NonNull Context context) {
    super.onAttach(context);
    // 获取Activity引用并执行初始化操作
}

2、onCreate(Bundle)

在Fragment创建时调用。可以在此方法中初始化一些数据和状态。

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 初始化数据和状态
}

3、onCreateView(LayoutInflater, ViewGroup, Bundle)

创建并返回Fragment的视图层次结构。

@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_layout, container, false);
    // 初始化视图
    return view;
}

4、onViewCreated(View, Bundle)

在Fragment的视图层次结构创建完成后调用。可以在此方法中进行视图的初始化操作。

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    // 初始化视图
}

5、onActivityCreated(Bundle)

在Activity的onCreate方法执行完毕后调用。

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    // 执行一些与Activity相关的操作
}

6、onStart()

当Fragment变为可见状态时调用


7、onResume()

当Fragment开始交互时调用。


8、onPause()

当Fragment从交互状态切换到暂停状态时调用。可以在此方法中释放一些资源。


9、onStop()

当Fragment不再可见时调用。


10、onDestroyView()

在Fragment的视图层次结构被销毁时调用。


11、onDestroy()

在Fragment被销毁之前调用。可以在此方法中释放资源。


12、onDetach()

当Fragment与Activity实例分离时调用。


此外,Fragment还提供了一些额外的生命周期回调方法,用于处理保存和恢复实例状态:

13、onSaveInstanceState(Bundle)

当Fragment需要保存状态时调用。可以在此方法中保存数据。

@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);
    // 保存数据
}

14、onViewStateRestored(Bundle)

在Fragment视图状态被恢复后调用。可以在此方法中恢复数据。

@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
    super.onViewStateRestored(savedInstanceState);
    // 恢复数据
}

三、Fragment的使用方式


在 Android 应用程序中使用 Fragment 有几种常见的方式,包括静态添加、动态添加和使用 FragmentManager 进行事务管理。下面通过 Java 代码示例演示每种方式:


1、静态添加 Fragment


静态添加 Fragment 是指在 Activity 的布局文件中直接定义 Fragment。这种方式适用于在应用启动时就需要显示的 Fragment。


(1)、 创建Fragment布局文件

首先,我们需要为每个Fragment创建一个布局文件。

fragment_a.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="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Fragment A"
        android:textSize="24sp" />

    <Button
        android:id="@+id/btn_fragment_a"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click Me" />

</LinearLayout>

fragment_b.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="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Fragment B"
        android:textSize="24sp" />

    <Button
        android:id="@+id/btn_fragment_b"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click Me" />

</LinearLayout>

(2)、 创建Fragment类


接下来,我们需要创建两个Fragment类,每个类对应一个Fragment布局。

FragmentA.java
public class FragmentA extends Fragment {

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_a, container, false);

        Button btnFragmentA = view.findViewById(R.id.btn_fragment_a);
        btnFragmentA.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 处理按钮点击事件
                Toast.makeText(getActivity(), "Fragment A Button Clicked", Toast.LENGTH_SHORT).show();
            }
        });

        return view;
    }
}
FragmentB.java
public class FragmentB extends Fragment {

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_b, container, false);

        Button btnFragmentB = view.findViewById(R.id.btn_fragment_b);
        btnFragmentB.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 处理按钮点击事件
                Toast.makeText(getActivity(), "Fragment B Button Clicked", Toast.LENGTH_SHORT).show();
            }
        });

        return view;
    }
}

(3)、 在Activity布局中静态添加Fragment

现在,我们将在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/fragment_a"
        android:name="com.example.FragmentA"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <fragment
        android:id="@+id/fragment_b"
        android:name="com.example.FragmentB"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

</LinearLayout>

在上面的布局文件中,我们使用<fragment>标签来静态添加两个Fragment。android:name属性指定了Fragment的完全限定类名,android:id属性为每个Fragment提供了一个唯一的标识符。


(4)、MainActivity

最后,我们只需要创建一个空的MainActivity即可,因为所有的Fragment都已经在布局文件中静态添加了。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

当你运行这个应用程序时,你会看到两个Fragment并排显示在屏幕上,每个Fragment中都有一个按钮。点击这些按钮会显示相应的Toast消息。


静态添加Fragment是一种简单而直接的方式,适用于在应用启动时就需要显示Fragment的情况。但是,如果你需要动态添加、移除或替换Fragment,那么你需要使用FragmentManager来管理Fragment事务。


2、动态添加 Fragment

动态添加 Fragment 是指在运行时通过代码将 Fragment 添加到 Activity 的布局中。这种方式适用于根据用户交互或其他条件动态显示 Fragment。

我们将创建一个主Activity,其布局文件中包含一个容器用于显示Fragment。我们将定义两个Fragment,并使用FragmentManager在容器中进行Fragment的添加、替换和移除操作。

(1)、 创建Fragment布局文件

首先,我们需要为每个Fragment创建一个布局文件。

fragment_a.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="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Fragment A"
        android:textSize="24sp" />

</LinearLayout>
fragment_b.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="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Fragment B"
        android:textSize="24sp" />

</LinearLayout>

(2)、创建Fragment类

接下来,我们需要创建两个Fragment类,每个类对应一个Fragment布局。

FragmentA.java
public class FragmentA extends Fragment {

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_a, container, false);
    }
}
FragmentB.java
public class FragmentB extends Fragment {

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_b, container, false);
    }
}

(3)、创建Activity布局

接下来,我们将创建Activity的布局文件,其中包含一个容器用于显示Fragment,以及四个按钮用于控制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="vertical">

    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btn_add_fragment_a"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Add Fragment A" />

        <Button
            android:id="@+id/btn_replace_fragment_b"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Replace with Fragment B" />

        <Button
            android:id="@+id/btn_remove_fragment"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Remove Fragment" />

        <Button
            android:id="@+id/btn_attach_fragment"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Attach Fragment" />

    </LinearLayout>

</LinearLayout>

在上面的布局文件中,我们使用<FrameLayout>作为容器来显示Fragment。下面的<LinearLayout>中包含四个按钮,分别用于添加FragmentA、替换为FragmentB、移除当前Fragment和附加Fragment。


(4)、 MainActivity

最后,我们将创建MainActivity并实现按钮的点击事件,用于动态添加和移除Fragment。

public class MainActivity extends AppCompatActivity {

    private FragmentManager fragmentManager;
    private FrameLayout fragmentContainer;
    private FragmentA fragmentA;
    private FragmentB fragmentB;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fragmentManager = getSupportFragmentManager();
        fragmentContainer = findViewById(R.id.fragment_container);

        Button btnAddFragmentA = findViewById(R.id.btn_add_fragment_a);
        btnAddFragmentA.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                addFragment(new FragmentA());
            }
        });

        Button btnReplaceFragmentB = findViewById(R.id.btn_replace_fragment_b);
        btnReplaceFragmentB.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                replaceFragment(new FragmentB());
            }
        });

        Button btnRemoveFragment = findViewById(R.id.btn_remove_fragment);
        btnRemoveFragment.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                removeFragment();
            }
        });

        Button btnAttachFragment = findViewById(R.id.btn_attach_fragment);
        btnAttachFragment.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                attachFragment();
            }
        });

        // 初始化并添加 FragmentA
        fragmentA = new FragmentA();
        addFragment(fragmentA);
    }

    private void addFragment(Fragment fragment) {
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.add(R.id.fragment_container, fragment);
        transaction.addToBackStack(null);
        transaction.commit();
    }

    private void replaceFragment(Fragment fragment) {
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.fragment_container, fragment);
        transaction.addToBackStack(null);
        transaction.commit();
    }

    private void removeFragment() {
        Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_container);
        if (fragment != null) {
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            transaction.remove(fragment);
            transaction.commit();
        }
    }

    private void attachFragment() {
        if (fragmentB == null) {
            fragmentB = new FragmentB();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            transaction.add(R.id.fragment_container, fragmentB);
            transaction.detach(fragmentB);
            transaction.commit();
        } else {
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            transaction.attach(fragmentB);
            transaction.commit();
        }
    }
}

MainActivity中,我们首先获取FragmentManager和容器FrameLayout的实例。然后,我们为三个按钮设置点击事件监听器。

  • "Add Fragment A"按钮会调用addFragment()方法,将FragmentA实例动态添加到容器中。
  • "Add Fragment B"按钮会调用addFragment()方法,将FragmentB实例动态添加到容器中。
  • "Remove Fragment"按钮会调用removeFragment()方法,移除当前容器中的Fragment。

addFragment()方法中,我们使用FragmentTransaction来添加Fragment。我们还调用了addToBackStack()方法,这样当用户按下返回键时,Fragment就会从容器中移除。

removeFragment()方法中,我们首先使用findFragmentById()方法获取当前容器中的Fragment实例。如果存在Fragment,我们就使用FragmentTransaction将其从容器中移除。


当你运行这个应用程序时,你会看到一个空白的容器和三个按钮。点击"Add Fragment A"或"Add Fragment B"按钮,相应的Fragment就会动态添加到容器中。点击"Remove Fragment"按钮,当前容器中的Fragment就会被移除。你还可以反复添加和移除Fragment,观察其行为。


3、使用 FragmentManager 管理 Fragment

FragmentManager 提供了一系列方法用于管理 Fragment 的生命周期和事务。我们可以使用它来添加、移除、替换和附加 Fragment。


public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 获取 FragmentManager
        FragmentManager fragmentManager = getSupportFragmentManager();

        // 开启一个事务
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

        // 替换 Fragment
        Fragment fragmentA = new FragmentA();
        fragmentTransaction.replace(R.id.fragment_container, fragmentA);

        // 提交事务
        fragmentTransaction.commit();
    }
}

MainActivity中,我们首先获取FragmentManager和容器FrameLayout的实例,并初始化fragmentAfragmentB实例。


然后,我们为四个按钮设置点击事件监听器:

  • "Add Fragment A"按钮会调用addFragment()方法,将FragmentA实例添加到容器中。

  • "Replace with Fragment B"按钮会调用replaceFragment()方法,用FragmentB实例替换当前容器中的Fragment。

  • "Remove Fragment"按钮会调用removeFragment()方法,移除当前容器中的Fragment。

  • "Attach Fragment"按钮会调用attachFragment()方法,首次点击时会添加并分离FragmentB实例,之后点击则会重新附加该Fragment实例。


让我们逐一了解这些方法的实现:

首先,addFragment()方法

private void addFragment(Fragment fragment) {
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    transaction.add(R.id.fragment_container, fragment);
    transaction.addToBackStack(null);
    transaction.commit();
}

这个方法使用FragmentTransaction来添加一个新的Fragment实例到容器中。我们调用add()方法来添加Fragment,并使用addToBackStack()方法将该事务添加到回退栈中,以便用户可以通过返回键来撤销该操作。


其次,replaceFragment()方法:

private void replaceFragment(Fragment fragment) {
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    transaction.replace(R.id.fragment_container, fragment);
    transaction.addToBackStack(null);
    transaction.commit();
}

这个方法使用FragmentTransaction将当前容器中的Fragment替换为一个新的Fragment实例。我们调用replace()方法来替换Fragment,并同样使用addToBackStack()方法将该事务添加到回退栈中。


然后,removeFragment()方法:

private void removeFragment() {
    Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_container);
    if (fragment != null) {
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.remove(fragment);
        transaction.commit();
    }
}

这个方法首先使用findFragmentById()方法获取当前容器中的Fragment实例。如果存在Fragment,我们就使用FragmentTransaction将其从容器中移除。


最后,attachFragment()方法:

private void attachFragment() {
    if (fragmentB == null) {
        fragmentB = new FragmentB();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.add(R.id.fragment_container, fragmentB);
        transaction.detach(fragmentB);
        transaction.commit();
    } else {
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.attach(fragmentB);
        transaction.commit();
    }
}

这个方法用于演示detach()attach()方法的使用。首次点击"Attach Fragment"按钮时,我们会添加一个新的FragmentB实例,然后立即将其分离。之后再次点击该按钮时,我们会重新附加该Fragment实例。这种做法可以在不销毁Fragment的情况下临时隐藏它,从而保留其状态。


在上面的代码中,我们还在onCreate()方法中初始化并添加了FragmentA实例。

当你运行这个应用程序时,你会看到一个显示FragmentA的容器和四个按钮。你可以尝试点击不同的按钮,观察Fragment的添加、替换、移除和附加/分离操作。

通过这个案例,能够更好地理解如何使用FragmentManager来管理Fragment的生命周期和事务。FragmentManager提供了丰富的方法,如add()replace()remove()attach()detach()等,让你可以灵活地控制Fragment的行为。你还可以使用addToBackStack()方法将Fragment事务添加到回退栈中,从而实现类似Activity的导航行为。


结语:

通过本文的深入解析,你应该对Fragment有了更全面的理解。无论是在构建新的应用还是优化现有项目,Fragment都是你不可或缺的工具。Fragment的潜力远不止于此。

在下一篇文章中,我们将探索如何使用Fragment实现更高级的界面切换效果,以及如何在Fragment之间传递数据。敬请期待!


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1651589.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024年成都市企业技术标准制(修)订申报条件奖励、材料流程须知

一、2022 年期间奖励项目 (一)申报条件 2022 年期间主导制(修)订并获批发布国际、国家和行业技术标准的工业和信息化企业(其中:民营企业获批发布时间在2022年1月1日至2022年12月31日期间&#xff0c;其他企业获批发布时间在2022年1月1日至2022年7月7日期间)。 (二)支持标准 …

Python | Leetcode Python题解之第76题最小覆盖子串

题目&#xff1a; 题解&#xff1a; class Solution:def minWindow(self, s: str, t: str) -> str:ans_left, ans_right -1, len(s)left 0cnt_s Counter() # s 子串字母的出现次数cnt_t Counter(t) # t 中字母的出现次数less len(cnt_t) # 有 less 种字母的出现次数…

车路云一体化简介

车路云一体化 车路云一体化融合控制系统&#xff08; System of Coordinated Control by Vehicle-Road-Cloud Integration&#xff0c;SCCVRCI&#xff09;&#xff0c;是利用新一代信息与通信技术&#xff0c; 将人、车、路、云的物理层、信息层、应用层连为一体&#xff0c;…

asp.net不用验证码包,如何实现手写验证码

引文&#xff1a;众所周知&#xff0c;一般我们日常碰到的验证码是一个图形样式的&#xff0c;列入这个样子的&#xff0c;那么在这个图片里面我们想实现我们自己界面上有这样的一个验证码就需要做两个操作&#xff0c;一个是在我们自己界面上生成如图所示的一个验证码图片&…

公司数据防泄漏方案分享|防泄密软件有哪些

企业的数据安全是公司稳定发展的必要条件&#xff0c;如何防止内部数据泄露企业的数据安全是公司稳定发展的必要条件&#xff0c;如何防止内部数据泄露已经成为了一个亟待解决的问题。在这个信息时代&#xff0c;数据已经成为企业最重要的资产之一&#xff0c;因此&#xff0c;…

125.两两交换链表中的节点(力扣)

题目描述 代码解决及思路 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), …

flutter安卓项目生成MD5、sha1、公钥等

一&#xff1a;MD5、SHA1等生成方式 工具&#xff1a;Android Studio 1. 打开flutter项目下的Android目录 2. 创建signingReport运行配置项 3. build apk&#xff1a; 导航栏->build->Generate Signed App Bundle / APK... 4. 填写存放路径&#xff0c;同时创建文件xx…

了解集合与数据结构(java)

什么是数据结构? 数据结构就是 数据结构, 功能就是描述和组织数据 比如我有10万个QQ号, 我来组织, 有很多种组织方法, 比如链表, 树, 堆, 栈等等. 假如QQ号要查找数据, 有种数据结构查找数据速度很快, 我们就用它 加入QQ号要进行删除数据, 有种数据结构删除速度很快, 我们…

编程入门(六)【Linux系统基础操作三】

读者大大们好呀&#xff01;&#xff01;!☀️☀️☀️ &#x1f525; 欢迎来到我的博客 &#x1f440;期待大大的关注哦❗️❗️❗️ &#x1f680;欢迎收看我的主页文章➡️寻至善的主页 文章目录 &#x1f525;前言&#x1f680;LInux的进程管理和磁盘管理top命令显示查看进…

【CTS :testExtensionAvailability】

【CTS】android.hardware.camera2.cts.CameraExtensionCharacteristicsTest#testExtensionAvailability 报错&#xff1a; java.lang.AssertionError: Extensions system property : true does not match with the advertised extensions: false expected: but was: 通过对这…

idea Maven 插件 项目多环境打包配置

背景 不同环境的配置文件不一样&#xff0c;打包方式也有差异 1. 准备配置文件 这里 local 为本地开发环境 可改为 dev 名称自定义 test 为测试环境 prod 为生产环境 根据项目业务自行定义 application.yml 配置&#xff1a; spring:profiles:#对应pom中的配置active: spring.…

VMware虚拟机中ubuntu使用记录(5)—— 如何在ubuntu中安装USB相机ros驱动并获取usb摄像头数据

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、ROS下USB相机驱动1.准备工作(1) 下载驱动(2) 创建ROS工作空间 2. 安装usb_cam驱动(1) 安装usb_cam驱动包(2) 编译代码 3. 修改usb_cam驱动的配置文件(1) 查看US…

电商大数据的采集||电商大数据关键技术【基于Python】

.电商大数据采集API 什么是大数据&#xff1f; 1.大数据的概念 大数据即字面意思&#xff0c;大量数据。那么这个数据量大到多少才算大数据喃&#xff1f;通常&#xff0c;当数据量达到TB乃至PB级别时&#xff0c;传统的关系型数据库在处理能力、存储效率或查询性能上可能会遇…

深度剖析Comate智能产品:科技巧思,实用至上

文章目录 Comate智能编码助手介绍Comate应用场景Comate语言与IDE支持 Comate安装步骤Comate智能编码使用体验代码推荐智能推荐生成单测注释解释注释生成智能问答 Comate实战演练总结 Comate智能编码助手介绍 市面上现在有很多智能代码助手&#xff0c;当时互联网头部大厂百度也…

泰克MSO64示波器的应用

泰克MSO64示波器是一款功能强大、多用途的数字示波器&#xff0c;具备高性能和灵活的测量功能&#xff0c;适用于各种应用场景。它不仅具备传统示波器的功能&#xff0c;还集成了逻辑分析仪的功能&#xff0c;能够同时观测和分析模拟和数字信号。下面将介绍泰克MSO64示波器在几…

一文读懂 SOLID 原则

大家好&#xff0c;我是孔令飞&#xff0c;字节跳动云原生开发专家、前腾讯云原生技术专家、云原生实战营 知识星球星主、《企业级 Go 项目开发实战》作者。欢迎关注我的公众号【令飞编程】&#xff0c;Go、云原生、AI 领域技术干货不错过。 在 Go 项目开发中&#xff0c;你经常…

【快捷部署】024_Hive(3.1.3)

&#x1f4e3;【快捷部署系列】024期信息 编号选型版本操作系统部署形式部署模式复检时间024Hive3.1.3Ubuntu 20.04tar包单机2024-05-07 一、快捷部署 #!/bin/bash ################################################################################# # 作者&#xff1a;cx…

【C++题解】1383. 奶牛和草丛

问题&#xff1a;1383. 奶牛和草丛 类型&#xff1a;深度搜索 题目描述&#xff1a; 奶牛Bessie计划好好享受柔软的春季新草。新草分布在 R 行 C 列的牧场里。它想计算一下牧场中的草丛数量。 在牧场地图中&#xff0c;每个草丛要么是单个“#”&#xff0c;要么是有公共边的相…

powershell 注册全局热键——提升效率小工具

powershell 注册全局热键 01 前言 在处理一些重复工作问题的时候&#xff0c;想搞一个小工具&#xff0c;配合全局快捷键来提高效率。因为是Windows系统&#xff0c;想到C#&#xff0c;但是又不想用VS开发&#xff0c;因为那样不够灵活&#xff0c;没办法随时修改随时用&…

构建 WebRTC 一对一信令服务器

构建 WebRTC 一对一信令服务器 构建 WebRTC 一对一信令服务器前言为什么选择 Nodejs&#xff1f;Nodejs 的基本原理浏览器使用 Nodejs安装 Nodejs 和 NPMsocket.io信令服务器搭建信令服务器客户端服务端启动服务器并测试 总结参考 构建 WebRTC 一对一信令服务器 前言 我们在学…