TabLayout+ViewPager实现滚动页面

news2024/7/6 20:31:14

目录

一、TabLayout介绍

二、TabLayout的常用属性和方法

常用属性:

 常用方法:

三、适配器介绍

(一)、PagerAdapter介绍:

(二)、FragmentPagerAdapter介绍:

(三)、FragmentStatePagerAdapter介绍:

 四、TabLayout+ViewPager例子 

 MainActivity:

MyFragmentPagerAdapter : 

MyFragmentStatePagerAdapter: 

 MyPagerAdapter :

 FirstFragment :

 activirt_main:

first_page: 

         运行结果:


一、TabLayout介绍

        TabLayout是Android Support库中的一个控件,它通常与ViewPager结合使用,用于实现多个页面的切换和导航。TabLayout通过标签页的形式展示不同的内容,用户可以通过点击标签页来切换不同的页面。

二、TabLayout的常用属性和方法

常用属性:

  1. tabMode:指定TabLayout的模式。可选值包括:fixed:固定模式,每个标签页的宽度相等。scrollable:可滚动模式,适用于较多标签页的情况。

  2. tabGravity:指定标签页在TabLayout中的对齐方式。可选值包括:fill:填充模式,将标签页平均分配在TabLayout中。center:居中模式,将标签页居中显示。start:起始模式,将标签页从起始位置开始排列。

  3. tabIndicatorColor:指定选中标签页底部指示器的颜色。

  4. tabIndicatorHeight:指定选中标签页底部指示器的高度(以像素为单位)。

  5. tabBackground:指定标签页的背景。

  6. tabTextAppearance:指定标签页的文本外观样式。可以使用自定义的样式资源。

  7. tabTextColor:指定标签页的文本颜色。

  8. tabSelectedTextColor:指定选中标签页的文本颜色。

  9. tabRippleColor:指定标签页的点击效果颜色。

  10. tabMaxWidth:指定标签页的最大宽度(以像素为单位)。

  11. tabContentStart:指定标签页内容的起始位置偏移量(以像素为单位)。

 常用方法:

1、newTab():创建一个新的标签页对象。

TabLayout.Tab tab = tabLayout.newTab();

2、addTab(Tab tab):添加一个标签页到TabLayout中。

tabLayout.addTab(tab);

3、removeTab(Tab tab):从TabLayout中移除指定的标签页。

tabLayout.removeTab(tab);

4、removeTabAt(int position):根据位置移除TabLayout中的标签页。

tabLayout.removeTabAt(position);

5、getTabCount():获取TabLayout中标签页的数量。

int count = tabLayout.getTabCount();

6、getTabAt(int position):根据位置获取TabLayout中指定的标签页。

TabLayout.Tab tab = tabLayout.getTabAt(position);

7、getSelectedTabPosition():获取当前选中的标签页的位置。

int selectedPosition = tabLayout.getSelectedTabPosition();

 8、setupWithViewPager(ViewPager viewPager):将TabLayout与ViewPager进行关联,实现标签页和页面的同步切换。

tabLayout.setupWithViewPager(viewPager);

9、setTabMode(int mode):设置TabLayout的模式,可以是TabLayout.MODE_FIXEDTabLayout.MODE_SCROLLABLE

tabLayout.setTabMode(TabLayout.MODE_FIXED);

10、setTabGravity(int gravity):设置标签页在TabLayout中的对齐方式,可以是TabLayout.GRAVITY_FILLTabLayout.GRAVITY_CENTERTabLayout.GRAVITY_START

tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);

11、setOnTabSelectedListener(OnTabSelectedListener listener):设置标签页选中状态监听器,用于监听标签页的选中和取消选中事件。

tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
    @Override
    public void onTabSelected(TabLayout.Tab tab) {
        // 处理选中事件
    }

    @Override
    public void onTabUnselected(TabLayout.Tab tab) {
        // 处理取消选中事件
    }

    @Override
    public void onTabReselected(TabLayout.Tab tab) {
        // 处理再次选中事件
    }
});

三、适配器介绍

(一)、PagerAdapter介绍:

        PagerAdapter是Android中的一个抽象类,用于在ViewPager中管理页面的适配器。它提供了统一的接口和方法,使得我们可以轻松地将不同的页面内容与ViewPager进行绑定并展示。

主要特点和使用方式如下:

  1. 页面管理:

    • PagerAdapter用于管理ViewPager中的页面,每个页面对应一个View。
    • 可以根据需要实现自定义的PagerAdapter来管理不同类型的页面。
  2. 常用方法:

    • instantiateItem(ViewGroup container, int position):根据position创建并返回对应页面的View对象。
    • destroyItem(ViewGroup container, int position, Object object):销毁指定位置的页面View对象。
    • getCount():返回页面的总数量。
    • isViewFromObject(View view, Object object):判断当前的View是否来自于指定的对象。
  3. 生命周期:

    • PagerAdapter会根据需要创建和销毁页面的View对象,并负责管理它们的生命周期。
    • 当某个页面不再可见时,对应的View可能会被销毁。当页面重新可见时,会重新创建对应的View对象。
  4. 数据更新:

    • 在PagerAdapter中,可以通过实现相关方法,如getItemPosition(Object object)或覆写notifyDataSetChanged()方法,实现数据的更新和重新加载页面的功能。

        PagerAdapter是一个抽象类,因此不能直接实例化,我们通常会使用其子类,如FragmentPagerAdapter或FragmentStatePagerAdapter,来管理Fragment页面。

        总之,PagerAdapter是用于在ViewPager中管理页面的抽象类,通过实现相关方法来创建、销毁和更新页面的View对象。它提供了一种灵活且可扩展的方式,使得我们能够根据需要定制自己的页面适配器。

(二)、FragmentPagerAdapter介绍:

  FragmentPagerAdapter是Android Support Library中的一个类,用于在ViewPager中展示Fragment的适配器。它继承自PagerAdapter,提供了便捷的方式来管理Fragment的展示和销毁。

使用FragmentPagerAdapter时,你需要继承该类并实现以下方法:

  1. getItem(int position):根据位置获取对应的Fragment对象。
  2. getCount():获取Fragment的数量。
  3. getPageTitle(int position):获取指定位置的Fragment的标题(用于TabLayout中展示)。
  4. instantiateItem(ViewGroup container, int position):创建指定位置的Fragment并添加到容器中。

(三)、FragmentStatePagerAdapter介绍:

        FragmentStatePagerAdapter是一个用于在ViewPager中展示Fragment的适配器,它继承自PagerAdapter类,并提供了一种管理Fragment的方式。它适用于有大量Fragment或动态数量的Fragment的场景。

主要特点和使用方式如下:

  1. Fragment管理方式:

    • FragmentStatePagerAdapter只会保留当前页面及其相邻页面的Fragment实例,而其他页面的Fragment会被销毁。这种方式可以节省内存并提高性能,特别适合于大量的Fragment或者动态数量的Fragment。
    • 当页面不再可见时,对应的Fragment可能会被销毁,但它的状态会保存下来,以便在需要时进行恢复。
  2. 常用方法:

    • getItem(int position):根据position返回对应位置的Fragment实例。
    • getCount():返回Fragment的总数量。
    • destroyItem(ViewGroup container,int position,Object object):销毁指定位置的Fragment实例。
  3. 生命周期:

    • FragmentStatePagerAdapter会根据需要创建和销毁Fragment实例,以保证内存的高效利用。
    • 当某个页面不可见时,对应的Fragment可能会被销毁,但它的状态会被保存。当页面重新可见时,会重新创建对应的Fragment实例。
  4. 数据加载和更新:

    • 在FragmentStatePagerAdapter中,可以使用getItem()方法根据position获取对应位置的Fragment实例,并在该Fragment中加载数据。
    • 当数据需要更新时,可以通过通知Fragment进行更新。

        总之,FragmentStatePagerAdapter适用于需要处理大量Fragment或动态数量的Fragment的场景。它在内存占用和性能优化方面提供了较好的支持,可以灵活管理Fragment的生命周期,并实现数据的加载和更新。

 四、TabLayout+ViewPager例子 

 MainActivity:

package com.example.viewpagerdemo;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.viewpager.widget.ViewPager;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;

import com.google.android.material.tabs.TabLayout;

import java.util.ArrayList;
import java.util.List;
/**
 * time:2023/7/15
 * author: 敬往事一杯酒
 */
public class MainActivity extends AppCompatActivity {


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

    /**
     * 使用PagerAdapter适配器实现翻转页面
     */
    private void initPagerAdapter() {
        FragmentManager fragmentManager = getSupportFragmentManager();
        ViewPager viewPager = findViewById(R.id.view_pager);
        List<View> views = new ArrayList<>();
        views.add(getLayoutInflater().inflate(R.layout.first_page,null));
        views.add(getLayoutInflater().inflate(R.layout.second_page,null));
        views.add(getLayoutInflater().inflate(R.layout.third_page,null));
        MyPagerAdapter fragmentAdapter = new MyPagerAdapter(views);
        viewPager.setAdapter(fragmentAdapter);
        // tabLayout跟viewpager关联
        TabLayout tabLayout = findViewById(R.id.tab_layout);
        tabLayout.setupWithViewPager(viewPager);
        // 设置每个标签的图标
        tabLayout.getTabAt(0).setIcon(R.drawable.ic_launcher_background);
        tabLayout.getTabAt(1).setIcon(R.drawable.ic_launcher_background);
        tabLayout.getTabAt(2).setIcon(R.drawable.ic_launcher_background);
    }


    /**
     * 使用FragmentStatePagerAdapter适配器实现翻转页面
     */
    private void initFragmentStatePagerAdapter(){
        FragmentManager fragmentManager = getSupportFragmentManager();
        ViewPager viewPager = findViewById(R.id.view_pager);
        List<Fragment> fragments = new ArrayList<>();
        fragments.add(new FirstFragment());
        fragments.add(new secondFragment());
        fragments.add(new ThirdFragment());
        MyFragmentStatePagerAdapter fragmentAdapter = new MyFragmentStatePagerAdapter(fragmentManager,fragments);
        viewPager.setAdapter(fragmentAdapter);
        // tabLayout跟viewpager关联
        TabLayout tabLayout = findViewById(R.id.tab_layout);
        tabLayout.setupWithViewPager(viewPager);
        // 设置每个标签的图标
        tabLayout.getTabAt(0).setIcon(R.drawable.ic_launcher_background);
        tabLayout.getTabAt(1).setIcon(R.drawable.ic_launcher_background);
        tabLayout.getTabAt(2).setIcon(R.drawable.ic_launcher_background);
    }
    /**
     * 使用FragmentPagerAdapter适配器实现翻转页面
     */
    private void initFragmentPagerAdapter(){
        FragmentManager fragmentManager = getSupportFragmentManager();
        ViewPager viewPager = findViewById(R.id.view_pager);
        List<Fragment> fragments = new ArrayList<>();
        fragments.add(new FirstFragment());
        fragments.add(new secondFragment());
        fragments.add(new ThirdFragment());
        MyFragmentPagerAdapter fragmentAdapter = new MyFragmentPagerAdapter(fragmentManager,fragments);
        viewPager.setAdapter(fragmentAdapter);
        // tabLayout跟viewpager关联
        TabLayout tabLayout = findViewById(R.id.tab_layout);
        tabLayout.setupWithViewPager(viewPager);
        // 设置每个标签的图标
        tabLayout.getTabAt(0).setIcon(R.drawable.ic_launcher_background);
        tabLayout.getTabAt(1).setIcon(R.drawable.ic_launcher_background);
        tabLayout.getTabAt(2).setIcon(R.drawable.ic_launcher_background);
    }
}

MyFragmentPagerAdapter : 

package com.example.viewpagerdemo;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;

import java.util.List;
/**
 * time:2023/7/15
 * author: 敬往事一杯酒
 */
public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
    private List<Fragment> mFragments;
    public MyFragmentPagerAdapter(@NonNull FragmentManager fm, List<Fragment>fragmentList) {
        super(fm);
        this.mFragments = fragmentList;
    }

    @NonNull
    @Override
    public Fragment getItem(int position) {
        return mFragments.get(position);
    }

    @Override
    public int getCount() {
        return mFragments.size();
    }
    @Nullable
    @Override
    public CharSequence getPageTitle(int position) {
        // 返回每个 Fragment 的标签文本
        switch (position) {
            case 0:
                return "第一页";
            case 1:
                return "第二页";
            case 2:
                return "第三页";
            default:
                return "";
        }
}}

MyFragmentStatePagerAdapter: 

package com.example.viewpagerdemo;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;

import java.util.List;
/**
 * time:2023/7/15
 * author: 敬往事一杯酒
 */
public class MyFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
    private List<Fragment> mFragments;
    public MyFragmentStatePagerAdapter(@NonNull FragmentManager fm,List<Fragment>fragments) {
        super(fm);
        mFragments = fragments;
    }

    @NonNull
    @Override
    public Fragment getItem(int position) {
        switch (position){
            case 0:
                return new FirstFragment();
            case 1:
                return new secondFragment();
            case 2:
                return new ThirdFragment();
            default:
                return null;
        }
    }


    @Override
    public int getCount() {
        if (mFragments!=null){

            return mFragments.size();
        }else {
            return 0;
    }
    }

    @Nullable
    @Override
    public CharSequence getPageTitle(int position) {
        // 返回每个 Fragment 的标签文本
        switch (position) {
            case 0:
                return "第一页";
            case 1:
                return "第二页";
            case 2:
                return "第三页";
            default:
                return "";
        }
    }
}

 MyPagerAdapter :

package com.example.viewpagerdemo;

import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.viewpager.widget.PagerAdapter;

import java.util.List;
/**
 * time:2023/7/15
 * author: 敬往事一杯酒
 */
public class MyPagerAdapter extends PagerAdapter {
    private List<View> mList;
    public MyPagerAdapter(List<View> list){
        this.mList = list;
    }
    // 返回要滑动的View的个数
    @Override
    public int getCount() {
        return mList.size();
    }
    // 创建指定位置的页面图
    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        container.addView(mList.get(position));
        return mList.get(position);
    }
    // instantiateItem返回的值是否与当前视图一样
    @Override
    public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
        return view==object;
    }
    // 移除一个给定位置的页面
    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        container.removeView(mList.get(position));
    }
    @Nullable
    @Override
    public CharSequence getPageTitle(int position) {
        // 返回每个 Fragment 的标签文本
        switch (position) {
            case 0:
                return "第一页";
            case 1:
                return "第二页";
            case 2:
                return "第三页";
            default:
                return "";
        }
    }
}

 FirstFragment :

package com.example.viewpagerdemo;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

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

 SecondFragmentThirdFragment代码和布局文件一样。

 activirt_main:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
   <com.google.android.material.tabs.TabLayout
       android:id="@+id/tab_layout"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_alignParentBottom="false"
       app:tabGravity="fill"
       app:tabMode="fixed" />

   <androidx.viewpager.widget.ViewPager
       android:id="@+id/view_pager"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:layout_below="@+id/tab_layout" />



</RelativeLayout>

first_page: 

<?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">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="第一个页面"
        android:textSize="25sp"
        />
</LinearLayout>

 运行结果:

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

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

相关文章

习题 1.26

我们先来看看题目要求&#xff0c;题目住说将 square 调用换成了&#xff08;* x x),结果导致执行时间变慢。 根据以前学过的内容&#xff0c;我们知道 在做显示乘法的时候&#xff0c;是直接进行计算的&#xff0c;而在做函数调用的时候&#xff0c;是先进行表达式展开的&…

【MySQL】常见函数使用(二)

&#x1f697;MySQL学习第二站~ &#x1f6a9;本文已收录至专栏&#xff1a;数据库学习之旅 ❤️文末附全文思维导图&#xff0c;感谢各位点赞收藏支持~ 就如同许多编程语言中的API一样&#xff0c;MySQL中的函数同样是官方给我们封装好的&#xff0c;可以直接调用的一段代码。…

ZooKeeper ZAB

文章首发地址 在接收到一个写请求操作后&#xff0c;追随者会将请求转发给群首&#xff0c;群首将探索性地执行该请求&#xff0c;并将执行结果以事务的方式对状态更新进行广播。一个事务中包含服务器需要执行变更的确切操作&#xff0c;当事务提交时&#xff0c;服务器就会将这…

dp算法篇Day7

"抱紧你的我&#xff0c;比国王富有~" 31、最长定差子序列 (1) 题目解析 从题目来看还是很容易理解的&#xff0c;就是找寻数组中构成差值相等的子序列。 (2) 算法原理 class Solution { public:int longestSubsequence(vector<int>& arr, int difference…

多模态系列论文--ALBEF 详细解析

ALBEF来自于Align before Fuse&#xff0c;作者团队全自来自于Salesforce Research。 论文地址&#xff1a;Align before Fuse: Vision and Language Representation Learning with Momentum Distillation 论文代码&#xff1a;ALBEF 1 摘要 最近图像文本的大规模的特征学习非…

AI Chat 设计模式:7. 单例模式

本文是该系列的第七篇&#xff0c;采用问答式的方式展开&#xff0c;问题由我提出&#xff0c;答案由 Chat AI 作出&#xff0c;灰色背景的文字则主要是我的旁白和思考。 问题列表 Q.1 简单介绍一下单例模式A.1Q.2 详细说说饿汉式&#xff0c;并使用 c 举例A.2Q.3 好&#xff…

【半监督医学图像分割 2022 IJCAI】UGPCL

文章目录 【半监督医学图像分割 2022 IJCAI】UGPCL摘要1. 介绍2. 相关工作2.1 半监督医学图像分割2.2 对比学习2.3 不确定度估计 3. 方法3.1 解码器间的一致性学习3.2 不确定性引导的对比学习3.3 等变对比损失 4. 实验4.1 实验设置4.2 定量实验4.3 消融实验 5. 结论 【半监督医…

引爆用户流量,打造热门小红书创业项目

引爆用户流量&#xff0c;打造热门小红书创业项目 在当今互联网时代&#xff0c;创业者们不断寻求新的商机和盈利模式。而小红书作为一个以分享购物心得、美妆、旅行等内容为主的社交平台&#xff0c;成为了众多创业者关注的焦点。如何通过小红书引爆用户流量&#xff0c;并打造…

【框架篇】使用注解存储对象

使用注解存储对象 之前我们存储Bean时&#xff0c;需要在spring-config 中添加一行 bean注册内容才行&#xff0c;如下图所示&#xff1a; 问题引入&#xff1a;如果想在Spring 中能够更简单的进行对象的存储和读取&#xff0c;该怎么办呢&#xff1f; 问题解答&#xff1a;实…

Python应用实例(一)外星人入侵(十)

外星人入侵&#xff08;十&#xff09; 1.记分1.1 显示得分1.2 创建记分牌1.3 在外星人被消灭时更新得分1.4 重置得分1.5 将消灭的每个外星人都计入得分1.6 提高分数1.7 舍入得分1.8 最高得分1.9 显示等级1.10 显示余下的飞船数 1.记分 下面来实现一个记分系统&#xff0c;以实…

动态规划01背包之1049 最后一块石头的重量 II(第11道)

题目&#xff1a; 有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 。那么粉碎的可能结果如下&#xff1a; …

4029: 网格行走

题目内容 在一个 n n n \times n nn 的网格上行走&#xff0c;从 ( 1 , 1 ) (1, 1) (1,1) 走到 ( n , n ) (n, n) (n,n)。每次只能向下走一步或向右走一步。 每个点 ( i , j ) (i, j) (i,j) 有权值 a i , j a_{i, j} ai,j​&#xff0c;给定一个数 x x x&#xff0c;求…

电机驱动系列(1)--例程下载演示

电机驱动系列&#xff08;1&#xff09; 使用设备连线实操感想 使用设备 硬件&#xff1a;野火骄阳板–STM32F407IGT6&#xff0c;野火无刷电机驱动板&#xff0c;PMSM电机软件&#xff1a;MCSDK&#xff0c;STM32CubeMX&#xff0c;Keil5软件安装注意事项&#xff1a;MCSDK-F…

SOF-SLAM论文翻译

SOF-SLAM:面向动态环境的语义可视化SLAM 摘要-同时定位与绘图(SLAM)在计算机视觉和机器人领域中占有重要地位。为了便于分析&#xff0c;传统的SLAM框架采用了强静态世界假设。如何应对动态环境是一个非常重要的问题&#xff0c;越来越受到人们的关注。现有的动态场景SLAM系统…

MySQL不适合创建索引的7种情况

1. 在where中使用不到的字段&#xff0c;不要设置索引 WHERE条件&#xff08;包括order by &#xff0c;group by&#xff09; 2. 数据量小的表最好不要使用索引 表记录太少&#xff0c;比如少于1000个&#xff0c;创建索引会先查索引&#xff0c;再回表&#xff0c;查询花费…

虚拟机安装及使用

无论下载什么软件&#xff0c;最好都要单独设置个文件夹 文章目录 VMware下载CentOS下载Xshell 7下载WinSCP下载linux命令 VMware下载 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; VMware Workstation Pro安装 一直傻瓜式安装 可以上网找许可证秘钥 …

asm: 实现打印“Hello, world!“

使用汇编打印“Hello, world!“ 实现打印"Hello, world!"的汇编代码代码详细剖析 实现打印"Hello, world!"的汇编代码 我们来直接贴代码 section .textglobal _start _start:mov edx,lenmov ecx,msgmov ebx,1mov eax,4 int 0x80mov …

pytest 通过装饰器获取测试case的断言失败结果

test11.py import logging from functools import wrapsdef log_exceptions(func):wraps(func)def wrapper(*args, **kwargs):# 创建日志记录器logger logging.getLogger(func.__name__)logger.setLevel(logging.ERROR)# 创建文件处理器file_handler logging.FileHandler(er…

MySQL(五)缓存策略

MySQL系列文章 MySQL&#xff08;一&#xff09;基本架构、SQL语句操作、试图 MySQL&#xff08;二&#xff09;索引原理以及优化 MySQL&#xff08;三&#xff09;SQL优化、Buffer pool、Change buffer MySQL&#xff08;四&#xff09;事务原理及分析 MySQL&#xff08;五&a…

利用pgloader工具将MySQL数据迁移至PostgreSQL数据库

一、简介 pgloader是一款开源软件,可以将各种来源的数据加载到PostgreSQL数据库中&#xff0c;支持动态读取数据&#xff0c;使用 COPY 流式传输协议将数据加载到 PostgreSQL 数据库中&#xff0c;并使用单独的线程读取和写入数据&#xff0c;由于能够直接从源数据库加载数据。…