Android 基于Fragment的权限封装

文章目录

  • Android 基于Fragment的权限封装
    • 原理
    • 代码
      • PermissionUtils.java
      • PermissionsFragment.java
      • PermissionHelper.java
      • SettingsFragment.java
      • Activity中使用
      • Fragment中使用
    • 源码

Android 基于Fragment的权限封装

原理

业内普遍比较认可使用另外一种小技巧来进行实现。是什么小技巧呢?回想一下,之前所有申请运行时权限的操作都是在 Activity 中进行的,事实上,Android 在 Fragment 中也提供了一份相同的 API,使得我们在 Fragment 中也能申请运行时权限。

但不同的是,Fragment 并不像 Activity 那样必须有界面,我们完全可以向 Activity 中添加一个隐藏的 Fragment,然后在这个隐藏的 Fragment 中对运行时权限的 API 进行封装。这是一种非常轻量级的做法,不用担心隐藏 Fragment 会对 Activity 的性能造成什么影响。

代码

PermissionUtils.java

/*** 权限工具类*/
public class PermissionUtils {public static final int REQUEST_SETTING_CODE = 0X123456;/*** 权限是否授予*/public static boolean isGranted(@NonNull Context context, @NonNull String permission) {return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;}/*** 权限是否全部授予*/public static boolean isGrantedPermissions(@NonNull Context context, @NonNull ArrayList<String> permissionList) {for (String permission : permissionList) {if (!isGranted(context, permission)) {return false;}}return true;}/*** 权限是否拒绝且不再询问*/public static boolean isDeniedNever(@NonNull Activity activity, @NonNull String permission) {return !ActivityCompat.shouldShowRequestPermissionRationale(activity, permission);}/*** 权限是否包含拒绝且不再询问*/public static boolean isDeniedNeverPermissions(@NonNull Activity activity, @NonNull ArrayList<String> permissions) {for (String permission : permissions) {if (isDeniedNever(activity, permission)) {return true;}}return false;}/*** 获取未授权权限*/public static ArrayList<String> getDeniedPermissions(@NonNull Context context, @NonNull ArrayList<String> permissionList) {ArrayList<String> deniedPermissionList = new ArrayList<>();for (String permission : permissionList) {if (!isGranted(context, permission)) {deniedPermissionList.add(permission);}}return deniedPermissionList;}/*** 获取包名Uri*/static Uri getPackageNameUri(@NonNull Context context) {return Uri.parse("package:" + context.getPackageName());}/*** 跳转设置界面*/public static void gotoSetting(@NonNull Activity activity) {Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);intent.setData(getPackageNameUri(activity));activity.startActivityForResult(intent, REQUEST_SETTING_CODE);}public static void gotoSetting(@NonNull Fragment fragment) {Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);intent.setData(getPackageNameUri(fragment.getContext()));fragment.startActivityForResult(intent, REQUEST_SETTING_CODE);}/*** 锁定屏幕方向*/public static void lockScreenOrientation(@NonNull Activity activity) {try {// 获取实际屏幕方向int screenOrientation = activity.getResources().getConfiguration().orientation;switch (screenOrientation) {case Configuration.ORIENTATION_LANDSCAPE:activity.setRequestedOrientation(PermissionUtils.isActivityReverse(activity) ?ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE :ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);break;case Configuration.ORIENTATION_PORTRAIT:activity.setRequestedOrientation(PermissionUtils.isActivityReverse(activity) ?ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT :ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);break;default:break;}} catch (Exception e) {e.printStackTrace();}}/*** Activity是否反方向旋转*/public static boolean isActivityReverse(@NonNull Activity activity) {int activityRotation;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {activityRotation = activity.getDisplay().getRotation();} else {activityRotation = activity.getWindowManager().getDefaultDisplay().getRotation();}switch (activityRotation) {case Surface.ROTATION_180:case Surface.ROTATION_270:return true;case Surface.ROTATION_0:case Surface.ROTATION_90:default:return false;}}
}

PermissionsFragment.java

/*** 权限请求Fragment*/
public class PermissionsFragment extends Fragment {public static final String REQUEST_CODE = "requestCode"; //请求码public static final String PARAM_PERMISSIONS = "permissionList";/*** 权限结果回调*/@Nullableprivate OnPermissionCallback mOnPermissionCallback;/*** 设置结果回调*/@Nullableprivate OnSettingsCallback mOnSettingsCallback;/*** 获取当前请求的屏幕方向*/private int mScreenOrientation;private PermissionHelper mHelper;private ArrayList<String> allPermissionList;private int mRequestCode;private static final ArrayList<Integer> requestCodeList = new ArrayList<>();public static void launch(@NonNull FragmentActivity activity, @NonNull ArrayList<String> permissionList, @NonNull PermissionHelper helper,@NonNull OnPermissionCallback onPermissionCallback, @Nullable OnSettingsCallback onSettingsCallback) {PermissionsFragment fragment = new PermissionsFragment();Bundle bundle = new Bundle();int requestCode = generateCode();bundle.putInt(REQUEST_CODE, requestCode);bundle.putStringArrayList(PARAM_PERMISSIONS, permissionList);fragment.setArguments(bundle);fragment.setRetainInstance(true);fragment.setCallback(onPermissionCallback, onSettingsCallback);fragment.setHelper(helper);fragment.attachActivity(activity);}private void setHelper(PermissionHelper helper) {mHelper = helper;}/*** 随机生成requestCode*/private static int generateCode() {int requestCode = new Random().nextInt(65536);while (requestCodeList.contains(requestCode)) {requestCode = new Random().nextInt(65536);}requestCodeList.add(requestCode);return requestCode;}/*** 绑定Activity*/private void attachActivity(@NonNull FragmentActivity activity) {activity.getSupportFragmentManager().beginTransaction().add(this, this.toString()).commitAllowingStateLoss();}/*** 解绑Activity*/private void detachActivity(@NonNull FragmentActivity activity) {activity.getSupportFragmentManager().beginTransaction().remove(this).commitAllowingStateLoss();}/*** 设置权限监听回调监听*/public void setCallback(@NonNull OnPermissionCallback onPermissionCallback, @Nullable OnSettingsCallback onSettingsCallback) {mOnPermissionCallback = onPermissionCallback;mOnSettingsCallback = onSettingsCallback;}@Overridepublic void onAttach(@NonNull Context context) {super.onAttach(context);FragmentActivity activity = getActivity();if (activity == null) {return;}Bundle bundle = getArguments();if (bundle != null) {ArrayList<String> permissionList = bundle.getStringArrayList(PARAM_PERMISSIONS);if (permissionList == null || permissionList.isEmpty()) {return;}mRequestCode = bundle.getInt(REQUEST_CODE);allPermissionList = permissionList;}// 获取请求的屏幕方向mScreenOrientation = activity.getRequestedOrientation();// 如果未指定屏幕方向,就锁定当前屏幕方向if (mScreenOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {PermissionUtils.lockScreenOrientation(activity);}}@Overridepublic void onDetach() {super.onDetach();FragmentActivity activity = getActivity();if (activity == null) {return;}// 如果当前屏幕方向是未指定,同时当前请求的屏幕方向是横屏或竖屏时,则屏幕方向切换为未指定方向模式if (mScreenOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED &&activity.getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);}}@Overridepublic void onResume() {super.onResume();requestPermissions(allPermissionList.toArray(new String[allPermissionList.size() - 1]), mRequestCode);}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NotNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (permissions.length == 0 || grantResults.length == 0) {return;}if (requestCode == mRequestCode) {FragmentActivity activity = getActivity();if (activity == null) {return;}ArrayList<String> grantedList = new ArrayList<>(); //已授予权限ArrayList<String> deniedList = new ArrayList<>(); //已拒绝权限for (int i = 0; i < grantResults.length; i++) {if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {deniedList.add(permissions[i]);} else {grantedList.add(permissions[i]);}}requestCodeList.remove((Integer) mRequestCode);OnPermissionCallback onPermissionCallback = mOnPermissionCallback;mOnPermissionCallback = null;OnSettingsCallback onSettingsCallback = mOnSettingsCallback;mOnSettingsCallback = null;PermissionHelper helper = mHelper;mHelper = null;detachActivity(activity);boolean allGranted = grantedList.size() == permissions.length;if (allGranted) {onPermissionCallback.onGranted(true, grantedList);return;}boolean deniedNever = PermissionUtils.isDeniedNeverPermissions(activity, deniedList);onPermissionCallback.onDenied(deniedNever, deniedList);if (grantedList.size() > 0) {onPermissionCallback.onGranted(false, grantedList);}if (deniedNever) {helper.showPermissionSettingDialog(activity, deniedList, onSettingsCallback);} else if (deniedList.size() > 0) {helper.showPermissionInfoDialog(activity, deniedList, onPermissionCallback, onSettingsCallback);}}}@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);}@Overridepublic void onDestroy() {super.onDestroy();mOnPermissionCallback = null;}
}
/*** 权限结果回调*/
public interface OnPermissionCallback {/*** 权限授予时回调** @param allGranted  是否全部被授予* @param permissions 已授予权限*/void onGranted(boolean allGranted, @NonNull ArrayList<String> permissions);/*** 权限拒绝时回调** @param deniedNever 是否拒绝且不再询问* @param permissions 被拒绝权限*/void onDenied(boolean deniedNever, @NonNull ArrayList<String> permissions);
}
public interface OnSettingsCallback {void onResult();
}

PermissionHelper.java

/*** 权限请求类*/
public class PermissionHelper {@Nullableprivate final FragmentActivity mActivity;@NonNullprivate final ArrayList<String> mPermissions = new ArrayList<>();private PermissionHelper(FragmentActivity activity) {mActivity = activity;}/*** 设置请求对象*/public static PermissionHelper with(FragmentActivity activity) {return new PermissionHelper(activity);}public static PermissionHelper with(Fragment fragment) {FragmentActivity activity = fragment.getActivity();return new PermissionHelper(activity);}public PermissionHelper permissions(@NonNull ArrayList<String> permissionList) {mPermissions.addAll(permissionList);return this;}/*** 请求权限*/public void request(@NonNull OnPermissionCallback onPermissionCallback) {request(onPermissionCallback, null);}public void request(@NonNull OnPermissionCallback onPermissionCallback, @Nullable OnSettingsCallback onSettingsCallback) {if (mActivity == null || mActivity.isFinishing() || mActivity.isDestroyed()) {return;}showPermissionInfoDialog(mActivity, mPermissions, onPermissionCallback, onSettingsCallback);}/*** 权限说明弹窗*/public void showPermissionInfoDialog(@NonNull FragmentActivity activity, @NonNull ArrayList<String> allPermissions, @NonNull OnPermissionCallback onPermissionCallback) {showPermissionInfoDialog(activity, allPermissions, onPermissionCallback, null);}public void showPermissionInfoDialog(FragmentActivity activity, @NonNull ArrayList<String> allPermissions, @NonNull OnPermissionCallback onPermissionCallback, @Nullable OnSettingsCallback onSettingsCallback) {if (activity == null || activity.isFinishing() || activity.isDestroyed()) {return;}ArrayList<String> permissionList = PermissionUtils.getDeniedPermissions(activity, allPermissions);String title = "权限说明";String message = "使用此功能需要先授予:" + listToString(getPermissionNames(permissionList));new AlertDialog.Builder(activity).setTitle(title).setMessage(message).setCancelable(false).setPositiveButton("授予", (dialog, which) -> {dialog.dismiss();PermissionsFragment.launch(activity, permissionList, this, onPermissionCallback, onSettingsCallback);}).setNegativeButton("取消", (dialog, which) -> {}).show();}/*** 获取权限名*/public static ArrayList<String> getPermissionNames(ArrayList<String> permissions) {ArrayList<String> permissionNames = new ArrayList<>();for (String permission : permissions) {switch (permission) {case Manifest.permission.CAMERA:permissionNames.add("相机权限");break;case Manifest.permission.ACCESS_FINE_LOCATION:permissionNames.add("定位权限");break;case Manifest.permission.CALL_PHONE:permissionNames.add("拨号权限");break;default:break;}}return permissionNames;}/*** ArrayList转String*/public static String listToString(ArrayList<String> permissionNames) {StringBuilder builder = new StringBuilder();for (int i = 0, size = permissionNames.size(); i < size; i++) {if (i == size - 1) {builder.append(permissionNames.get(i));} else {builder.append(permissionNames.get(i)).append("、");}}return builder.toString();}/*** 权限提醒弹窗*/public void showPermissionSettingDialog(FragmentActivity activity, ArrayList<String> permissionList, @Nullable OnSettingsCallback onSettingsCallback) {if (activity == null || activity.isFinishing() || activity.isDestroyed()) {return;}String title = "权限提醒";String message = "获取权限失败,请手动授予:" + listToString(getPermissionNames(permissionList));new AlertDialog.Builder(activity).setTitle(title).setMessage(message).setPositiveButton("前往授权", (dialog, which) -> {dialog.dismiss();SettingsFragment.launch(activity, onSettingsCallback);}).show();}
}

SettingsFragment.java

/*** 跳转设置页Fragment*/
public class SettingsFragment extends Fragment {@Nullableprivate OnSettingsCallback mCallBack;public static void launch(@NonNull FragmentActivity activity, @Nullable OnSettingsCallback callback) {SettingsFragment fragment = new SettingsFragment();fragment.setRetainInstance(true);if (callback != null)fragment.setCallback(callback);fragment.attachActivity(activity);}/*** 设置回调*/public void setCallback(@NonNull OnSettingsCallback callback) {mCallBack = callback;}/*** 绑定Activity*/private void attachActivity(@NonNull FragmentActivity activity) {activity.getSupportFragmentManager().beginTransaction().add(this, this.toString()).commitAllowingStateLoss();}/*** 解绑Activity*/private void detachActivity(@NonNull FragmentActivity activity) {activity.getSupportFragmentManager().beginTransaction().remove(this).commitAllowingStateLoss();}@Overridepublic void onResume() {super.onResume();PermissionUtils.gotoSetting(this);}@Overridepublic void onActivityResult(int requestCode, int resultCode, @Nullable @org.jetbrains.annotations.Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == PermissionUtils.REQUEST_SETTING_CODE) {OnSettingsCallback callback = mCallBack;mCallBack = null;if (callback != null) {callback.onResult();}}FragmentActivity activity = getActivity();if (activity == null) {return;}detachActivity(activity);}@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);}@Overridepublic void onDestroy() {super.onDestroy();mCallBack = null;}
}

Activity中使用

{ArrayList<String> permissionList = new ArrayList<>();permissionList.add(Manifest.permission.CAMERA);permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);permissionList.add(Manifest.permission.CALL_PHONE);if (PermissionUtils.isGrantedPermissions(mContext, permissionList)) {Toast.makeText(mContext, "权限都通过了", Toast.LENGTH_SHORT).show();} else {PermissionHelper.with(this).permissions(permissionList).request(new OnPermissionCallback() {@Overridepublic void onGranted(boolean allGranted, @NonNull ArrayList<String> permissions) {if (allGranted) {Toast.makeText(mContext, "权限全部通过", Toast.LENGTH_SHORT).show();}Log.e("TAG", "onGranted: " + allGranted + " - " + permissions);}@Overridepublic void onDenied(boolean deniedNever, @NonNull ArrayList<String> permissions) {if (deniedNever) {Toast.makeText(mContext, "权限拒绝且不再询问", Toast.LENGTH_SHORT).show();}Log.e("TAG", "onDenied: " + deniedNever + " - " + permissions);}}, new OnSettingsCallback() {@Overridepublic void onResult() {Log.e("TAG", "onResult");}});}
}

Fragment中使用

ArrayList<String> permissionList = new ArrayList<>();
permissionList.add(Manifest.permission.CAMERA);
permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);
permissionList.add(Manifest.permission.CALL_PHONE);if (PermissionUtils.isGrantedPermissions(mContext, permissionList)) {Toast.makeText(mContext, "权限都通过了", Toast.LENGTH_SHORT).show();
} else {PermissionHelper.with(this).permissions(permissionList).request(new OnPermissionCallback() {@Overridepublic void onGranted(boolean allGranted, @NonNull ArrayList<String> permissions) {if (allGranted) {Toast.makeText(mContext, "权限全部通过", Toast.LENGTH_SHORT).show();}Log.e("TAG", "onGranted: " + allGranted + " - " + permissions);}@Overridepublic void onDenied(boolean deniedNever, @NonNull ArrayList<String> permissions) {if (deniedNever) {Toast.makeText(mContext, "权限拒绝且不再询问", Toast.LENGTH_SHORT).show();}Log.e("TAG", "onDenied: " + deniedNever + " - " + permissions);}}, new OnSettingsCallback() {@Overridepublic void onResult() {Log.e("TAG", "onResult");}});
}

源码

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

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

相关文章

51-16 FusionAD 用于自动驾驶预测与规划任务的多模态融合论文精读

今天要分享的是基于BEV的多模态、多任务、端到端自动驾驶模型FusionAD&#xff0c;其专注于自动驾驶预测和规划任务。这项工作首次发表于2023年8月2日&#xff0c;性能超越了2023 CVPR最佳论文UniAD模型。论文题目是FusionAD: Multi-modality Fusion for Prediction and Planni…

记录一些随机约束的控制方法

文章目录 前言一、内嵌约束控制二、控制rand变量是否随机三、选择随机控制的变量四、控制约束块是否随机五、约束的嵌套控制总结 前言 在运用UVM验证过程中&#xff0c;经常会用到大量的随机&#xff0c;这个时候我们需要控制随机约束的打开或者关闭&#xff0c;来实现不同模式…

linux显示系统内存使用情况--free命令

free 命令是Linux系统中用于显示系统内存使用情况的一个常用工具。通过该命令&#xff0c;用户可以轻松了解系统的内存分配、使用情况以及性能状况。本文将深入介绍free命令的各个方面&#xff0c;并提供详细的示例。 安装与基本用法 通常来说&#xff0c;free命令已经预装在大…

汽车数据解决方案:通过更好的数据提高速度

无论您是负责数字化转型的 CIO 或 IT 团队&#xff0c;还是实施 IoT 和 AI 洞察的工厂经理&#xff0c;或者是管理复杂数据管道的 ADAS 和无人驾驶团队&#xff0c;我们都可以帮您在数据发展曲线上保持领先。 全球数字化浪潮下&#xff0c;传统汽车行业生产模式、制造模式、服…

基于Python实现人脸识别相似度对比

目录 引言背景介绍目的和意义 人脸识别的原理人脸图像获取人脸检测与定位人脸特征提取相似度计算 基于Python的人脸相似度对比实现数据集准备人脸图像预处理特征提取相似度计算 引言 背景介绍 人脸识别技术是一种通过计算机对人脸图像进行分析和处理&#xff0c;从而实现自动识…

2023.1.17 关于 Redis 持久化 AOF 策略详解

目录 引言 AOF 策略 实例演示一 缓冲区 重写机制 手动触发 自动触发 AOF 重写流程 实例演示二 引言 Redis 实现持久化的两大策略 RDB ——> Redis DataBase&#xff08;定期备份&#xff09;AOF ——> Append Only File&#xff08;实时备份&#xff09; 注意&…

JavaEE:多线程(2):线程状态,线程安全

目录 线程状态 线程安全 线程不安全 加锁 互斥性 可重入 死锁 死锁的解决方法 Java标准库中线程安全类 内存可见性引起的线程安全问题 等待和通知机制 线程饿死 wait notify 线程状态 就绪&#xff1a;线程随时可以去CPU上执行&#xff0c;也包含在CPU上执行的…

漏洞补丁修复之openssl版本从1.1.1q升级到1.1.1t以及python版本默认2.7.5升级到2.7.18新版本和Nginx版本升级到1.24.0

​ 一、Openssl升级 1、查看Openssl安装的版本 openssl version 2、查看Openssl路径 which openssl 3、上传openssl安装包到服务器:openssl-1.1.1t.tar.gz,并且解压,安装: mv /usr/local/openssl /usr/local/backup_openssl_1.1.1q_20240120 mkdir /usr/local/openssl tar…

强化学习:MuJoCo机器人强化学习仿真入门

声明&#xff1a;我们跳过mujoco环境的搭建&#xff0c;搭建环境不难&#xff0c;可自行百度 下面开始进入正题&#xff08;需要有一定的python基础与xml基础&#xff09;&#xff1a; 下面进入到建立机器人模型的部分&#xff1a; 需要先介绍URDF模型文件和导出MJCF格式 介绍完…

K8S--安装Nginx

原文网址&#xff1a;K8S--安装Nginx-CSDN博客 简介 本文介绍K8S安装Nginx的方法。 1.创建Nginx目录及配置文件 mkdir -p /work/devops/k8s/app/nginx/{config,html} 在config目录下创建nginx.conf配置文件&#xff0c;内容如下&#xff1a; # events必须要有 events {wo…

PALWORLD linux centos7开服教程

开放端口8211 iptables -A INPUT -p udp -p tcp --dport 8211 -j ACCEPT iptables -A INPUT -p udp -p udp --dport 8211 -j ACCEPT yum -y install glibc.i686 libstdc.i686 screen libcurl.i686 yum install glibc-devel.i686 yum install libstdc-devel.i686 yum -y ins…

C#设计模式教程(18):中介者模式

中介者模式的定义 中介者模式(Mediator Pattern)是一种行为设计模式,它允许一组对象相互通信,而不需要知道彼此的内部结构。这样做可以降低多个对象和类之间的通信复杂性,将多对多的通信转变为一对多的通信,使得对象之间的耦合松散,并且可以更容易地独立地改变和复用这…

逆序对数量(归并排序做法)

先给出上一篇文章归并排序模板-CSDN博客里的归并排序模板&#xff1a; #include<iostream> using namespace std;const int N 100010;int n; int q[N], temp[N];void merge_sort(int q[], int l, int r) {if(l > r) return;int mid (lr) >> 1;merge_sort(q, …

【代码随想录算法训练营-第十天】【栈与队列】232.用栈实现队列,225. 用队列实现栈

写在最前面&#xff0c;目前Java已经推荐使用Deque来实现栈和队列了&#xff0c;原因&#xff1a; https://www.cnblogs.com/jiading/articles/12452830.html 232.用栈实现队列 第一遍 思路 pop&#xff1a;出栈&#xff1b;push&#xff1a;入栈&#xff1b;peek&#xff1…

爬虫安居客新房

一、首先看网址 后面有全部代码 https://hf.fang.anjuke.com/loupan/baohequ/p3 这种形式很好分析&#xff0c;https://hf.fang.anjuke.com/loupan/行政区域页码 xinfang_area ["feixixian", "baohequ", "shushanqu", "luyangqu",…

#GPU|LLM|AIGC#集成显卡与独立显卡|显卡在深度学习中的选择与LLM GPU推荐

区别 核心区别&#xff1a;显存&#xff0c;也被称作帧缓存。独立显卡拥有独立显存&#xff0c;而集成显卡通常是没有的&#xff0c;需要占用部分主内存来达到缓存的目的 集成显卡&#xff1a; 是集成在主板上的&#xff0c;与主处理器共享系统内存。 一般会在很多轻便薄型的…

从0开始学mysql 第十课:MySQL 自定义函数

第十课&#xff1a;MySQL 自定义函数 学习目标 本课程将指导你&#xff1a; 理解自定义函数的概念及其与存储过程的区别。学习如何创建自定义函数。掌握在查询中调用自定义函数的方法。了解如何管理&#xff08;更新和删除&#xff09;自定义函数。对自定义函数的性能及最佳…

机械臂雅可比矩阵的矢量积理解和matlab实现

雅可比矩阵的第Ji列&#xff1a; 关于一些基本概念可以参考博客&#xff0c;部分细节如下&#xff1a; 每个移动关节&#xff0c;Ji可以这样计算&#xff1a; 每个旋转关节&#xff0c;Ji这样计算&#xff1a; 有时候要求按照末端执行器坐标系{n}来执行一些位移旋转之类的…

C# Queryable类

文章目录 前言一、Queryable二、Queryable类中的方法大致分类三、与Lambda表达式结合使用四 、Queryable 与java的Stream 相比较基本概念查询语法QueryableStream 性能和延迟执行实际项目选择考虑因素 总结 前言 C# 学习入门系列&#xff0c;C# 中的 Queryable类 一、Queryabl…

uniapp中vue2项目导入高德地图

1、看官网新手入门链接导入原生高德地图&#xff1a; JS API 结合 Vue 使用-基础-进阶教程-地图 JS API 2.0|高德地图API (amap.com) 具体步骤&#xff1a; 第一步&#xff0c;安装插件 npm i amap/amap-jsapi-loader --save 第二步&#xff0c;在vue组件中写代码显示地图…