文章目录

    • 一、高度设置wrap_content无效?
    • 二、setOffscreenPageLimit(0)不起作用?
    • 三、Viewpager+Fragment组合使用

一、高度设置wrap_content无效?

当给ViewPager的高度设置为wrap_content,并不会生效,原因在于onMeasure方法。onMeasure方法实用类测量宽高的,so每个View都会有自己的onMeasure方法。讲道理人家(的onMeasure方法)会先测量child的高度,最后再通过setMeasuredDimension方法测量并设置自己的宽高。

然而,ViewPager并没有这么做!上来就调用setMeasuredDimension方法设置自己的宽高,根本没有管它的child,简直就不是亲生的!

this.setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec));

从这行代码可以看出,VP将自己默认的size设为0,优先使用父布局传过来的widthMeasureSpec、heightMeasureSpec。结果就是如果不指定宽高,就使用match_parent。 只要VP符合它自己的parent的要求,VP就会快速的它的parent填充满,其他的一概不管。也许VP如此对待它的child的原因在于child可被动态的添加、删除,宽高并不确定!

要想解决这个问题,其实也很简单:只需要自定义ViewPager并重写onMeasure方法即可。在onMeasure方法中,先遍历自己所有的child并计算它们的高度,最后再调用父类的onMeasure方法,将得到的宽高传入:

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

二、setOffscreenPageLimit(0)不起作用?

Fragment+ViewPager组合使用时,调用setOffscreenPageLimit(0)设置当前页面下左右两边缓存的item个数为0,无效。

public void setOffscreenPageLimit(int limit) {if (limit < 1) {Log.w("ViewPager", "Requested offscreen page limit " + limit + " too small; defaulting to " + 1);limit = 1;}if (limit != this.mOffscreenPageLimit) {this.mOffscreenPageLimit = limit;this.populate();}}

从以上代码中就能找到证据,当limit < 1时,limit = 1。也就是说即使设置缓存数为0,ViewPager始终还是会额外的去缓存下一个。对于VP+Fragment组合的使用场景而言,curItem是可见的,curItem+1无需展示,这样也会在请求网络上造成时间压力。

ViewPager + Adapter结合使用,VP是如何从Adapter处获取、销毁的数据呢?这就引出了一个神秘方法–populate() 。

populate() 是专门用来计算、处理缓存的,populate() 函数的生命周期是和Adapter的生命周期同步的。ViewPager能够顺利的对数据进行获取、销毁等操作,全部都依赖于populate() 。

 void populate(int newCurrentItem) {ViewPager.ItemInfo oldCurInfo = null;if (this.mCurItem != newCurrentItem) {oldCurInfo = this.infoForPosition(this.mCurItem);this.mCurItem = newCurrentItem;}if (this.mAdapter == null) {this.sortChildDrawingOrder();} else if (this.mPopulatePending) {this.sortChildDrawingOrder();} else if (this.getWindowToken() != null) {this.mAdapter.startUpdate(this);// --->更新int pageLimit = this.mOffscreenPageLimit;int startPos = Math.max(0, this.mCurItem - pageLimit);int N = this.mAdapter.getCount();// --->获取Adapter的数据量int endPos = Math.min(N - 1, this.mCurItem + pageLimit);// 缓存空间[startPos,endPos] ---> [mCurItem-pageLimit,mCurItem+pageLimit]if (N != this.mExpectedAdapterCount) {String resName;try {resName = this.getResources().getResourceName(this.getId());} catch (NotFoundException var17) {resName = Integer.toHexString(this.getId());}throw new IllegalStateException("The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged! Expected adapter item count: " + this.mExpectedAdapterCount + ", found: " + N + " Pager id: " + resName + " Pager class: " + this.getClass() + " Problematic adapter: " + this.mAdapter.getClass());} else {int curIndex = true;ViewPager.ItemInfo curItem = null;int curIndex;for(curIndex = 0; curIndex < this.mItems.size(); ++curIndex) {ViewPager.ItemInfo ii = (ViewPager.ItemInfo)this.mItems.get(curIndex);if (ii.position >= this.mCurItem) {if (ii.position == this.mCurItem) {curItem = ii;}break;}}//curItem没找到,即没有缓存,就先加载一个itemif (curItem == null && N > 0) {curItem = this.addNewItem(this.mCurItem, curIndex);}int itemIndex;ViewPager.ItemInfo ii;int i;if (curItem != null) {//先对左边的item进行缓存处理float extraWidthLeft = 0.0F;itemIndex = curIndex - 1;ii = itemIndex >= 0 ? (ViewPager.ItemInfo)this.mItems.get(itemIndex) : null;i = this.getClientWidth();float leftWidthNeeded = i <= 0 ? 0.0F : 2.0F - curItem.widthFactor + (float)this.getPaddingLeft() / (float)i;for(int pos = this.mCurItem - 1; pos >= 0; --pos) {if (extraWidthLeft >= leftWidthNeeded && pos < startPos) {if (ii == null) {break;}// 缓存区间之外的item,要destory掉if (pos == ii.position && !ii.scrolling) {this.mItems.remove(itemIndex);this.mAdapter.destroyItem(this, pos, ii.object);// --->销毁item--itemIndex;--curIndex;ii = itemIndex >= 0 ? (ViewPager.ItemInfo)this.mItems.get(itemIndex) : null;}} else if (ii != null && pos == ii.position) {extraWidthLeft += ii.widthFactor;--itemIndex;ii = itemIndex >= 0 ? (ViewPager.ItemInfo)this.mItems.get(itemIndex) : null;} else { //如果item没有出现过,就去addNewItemii = this.addNewItem(pos, itemIndex + 1);extraWidthLeft += ii.widthFactor;++curIndex;ii = itemIndex >= 0 ? (ViewPager.ItemInfo)this.mItems.get(itemIndex) : null;}}//再对右边的item进行缓存处理float extraWidthRight = curItem.widthFactor;itemIndex = curIndex + 1;if (extraWidthRight < 2.0F) {ii = itemIndex < this.mItems.size() ? (ViewPager.ItemInfo)this.mItems.get(itemIndex) : null;float rightWidthNeeded = i <= 0 ? 0.0F : (float)this.getPaddingRight() / (float)i + 2.0F;for(int pos = this.mCurItem + 1; pos < N; ++pos) {if (extraWidthRight >= rightWidthNeeded && pos > endPos) {if (ii == null) {break;}if (pos == ii.position && !ii.scrolling) {this.mItems.remove(itemIndex);this.mAdapter.destroyItem(this, pos, ii.object);ii = itemIndex < this.mItems.size() ? (ViewPager.ItemInfo)this.mItems.get(itemIndex) : null;}} else if (ii != null && pos == ii.position) {extraWidthRight += ii.widthFactor;++itemIndex;ii = itemIndex < this.mItems.size() ? (ViewPager.ItemInfo)this.mItems.get(itemIndex) : null;} else {ii = this.addNewItem(pos, itemIndex);++itemIndex;extraWidthRight += ii.widthFactor;ii = itemIndex < this.mItems.size() ? (ViewPager.ItemInfo)this.mItems.get(itemIndex) : null;}}}this.calculatePageOffsets(curItem, curIndex, oldCurInfo);this.mAdapter.setPrimaryItem(this, this.mCurItem, curItem.object); // --->设置当前的item}this.mAdapter.finishUpdate(this);// --->完成更新int childCount = this.getChildCount();for(itemIndex = 0; itemIndex < childCount; ++itemIndex) {View child = this.getChildAt(itemIndex);ViewPager.LayoutParams lp = (ViewPager.LayoutParams)child.getLayoutParams();lp.childIndex = itemIndex;if (!lp.isDecor && lp.widthFactor == 0.0F) {ViewPager.ItemInfo ii = this.infoForChild(child);if (ii != null) {lp.widthFactor = ii.widthFactor;lp.position = ii.position;}}}this.sortChildDrawingOrder();if (this.hasFocus()) {View currentFocused = this.findFocus();ii = currentFocused != null ? this.infoForAnyChild(currentFocused) : null;if (ii == null || ii.position != this.mCurItem) {for(i = 0; i < this.getChildCount(); ++i) {View child = this.getChildAt(i);ii = this.infoForChild(child);if (ii != null && ii.position == this.mCurItem && child.requestFocus(2)) {break;}}}}}}}

首先关注一点:

curItem = this.addNewItem(this.mCurItem, curIndex);

一旦没找到curItem,即没有缓存,就先加载一个item。curItem是通过addNewItem方法来确定的:

ViewPager.ItemInfo addNewItem(int position, int index) {ViewPager.ItemInfo ii = new ViewPager.ItemInfo();ii.position = position;//ItemInfo中的object就是缓存的Viewii.object = this.mAdapter.instantiateItem(this, position);ii.widthFactor = this.mAdapter.getPageWidth(position);if (index >= 0 && index < this.mItems.size()) {this.mItems.add(index, ii);} else {this.mItems.add(ii);}return ii;}

而在addNewItem函数中,我们可以发现Adapter的身影:this.mAdapter.instantiateItem(this, position)。也就是说创建新的Item要通过Adapter,恰巧instantiateItem方法的作用就是用来构建新的View并return。

其实,只要仔细观察Adapter的方法:

public abstract int getCount();
public void startUpdate(@NonNull ViewGroup container)
public Object instantiateItem(@NonNull ViewGroup container, int position)
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) 
public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object)
public void finishUpdate(@NonNull ViewGroup container)
......

在populate()方法中都能看到他们被调用的身影:

this.mAdapter.startUpdate(this);// --->更新
int N = this.mAdapter.getCount();// --->获取Adapter的数据量
this.mAdapter.destroyItem(this, pos, ii.object);// --->销毁item
this.mAdapter.setPrimaryItem(this, this.mCurItem, curItem.object); // --->设置当前的item
this.mAdapter.finishUpdate(this);// --->完成更新
......

这意味着,populate()函数贯穿了整个Adapter的各个函数的调用过程,等同于populate()方法的生命周期和Adapter已经融合在一起了。换句话说,Adapter的所有动作都是由populate()方法操控的,即每个Item的管理实际上都是由populate()方法控制的。可以得出结论:VP的缓存的幕后黑手是populate()。就好比是宇智波带土一直在用写轮眼控制三尾人柱力矢仓,对鬼鲛下达命令。

说道缓存,仔细看populate()方法中的startPos和endPos。VP的缓存空间就是[startPos,endPos] —> [mCurItem-pageLimit,mCurItem+pageLimit]。这里的pageLimit就是我们在Java代码中调用setOffscreenPageLimit(n)时传入的值。这样计算来,VP缓存的是[当前Item-pageLimit,当前Item+pageLimit]。

在完成更新之前,要对左右两边的缓存进行处理:

if (curItem != null) {//先对左边的item进行缓存处理float extraWidthLeft = 0.0F;itemIndex = curIndex - 1;ii = itemIndex >= 0 ? (ViewPager.ItemInfo)this.mItems.get(itemIndex) : null;i = this.getClientWidth();float leftWidthNeeded = i <= 0 ? 0.0F : 2.0F - curItem.widthFactor + (float)this.getPaddingLeft() / (float)i;for(int pos = this.mCurItem - 1; pos >= 0; --pos) {if (extraWidthLeft >= leftWidthNeeded && pos < startPos) {if (ii == null) {break;}// 缓存区间之外的item,要destory掉if (pos == ii.position && !ii.scrolling) {this.mItems.remove(itemIndex);this.mAdapter.destroyItem(this, pos, ii.object);// --->销毁item--itemIndex;--curIndex;ii = itemIndex >= 0 ? (ViewPager.ItemInfo)this.mItems.get(itemIndex) : null;}} else if (ii != null && pos == ii.position) {extraWidthLeft += ii.widthFactor;--itemIndex;ii = itemIndex >= 0 ? (ViewPager.ItemInfo)this.mItems.get(itemIndex) : null;} else { //如果item没有出现过,就去addNewItemii = this.addNewItem(pos, itemIndex + 1);extraWidthLeft += ii.widthFactor;++curIndex;ii = itemIndex >= 0 ? (ViewPager.ItemInfo)this.mItems.get(itemIndex) : null;}}//再对右边的item进行缓存处理float extraWidthRight = curItem.widthFactor;itemIndex = curIndex + 1;if (extraWidthRight < 2.0F) {ii = itemIndex < this.mItems.size() ? (ViewPager.ItemInfo)this.mItems.get(itemIndex) : null;float rightWidthNeeded = i <= 0 ? 0.0F : (float)this.getPaddingRight() / (float)i + 2.0F;for(int pos = this.mCurItem + 1; pos < N; ++pos) {if (extraWidthRight >= rightWidthNeeded && pos > endPos) {if (ii == null) {break;}if (pos == ii.position && !ii.scrolling) {this.mItems.remove(itemIndex);this.mAdapter.destroyItem(this, pos, ii.object);ii = itemIndex < this.mItems.size() ? (ViewPager.ItemInfo)this.mItems.get(itemIndex) : null;}} else if (ii != null && pos == ii.position) {extraWidthRight += ii.widthFactor;++itemIndex;ii = itemIndex < this.mItems.size() ? (ViewPager.ItemInfo)this.mItems.get(itemIndex) : null;} else {ii = this.addNewItem(pos, itemIndex);++itemIndex;extraWidthRight += ii.widthFactor;ii = itemIndex < this.mItems.size() ? (ViewPager.ItemInfo)this.mItems.get(itemIndex) : null;}}}this.calculatePageOffsets(curItem, curIndex, oldCurInfo);this.mAdapter.setPrimaryItem(this, this.mCurItem, curItem.object); // --->设置当前的item}

处理顺序为:先左右后。缓存区间之外的Item要及时destroyItem销毁掉。当然,如果Item没有出现,就先去addNewItem构建出一个Item来,并保存到mItems中。这个mItems是专门用来缓存的ArrayList:

//mItems是专门用来缓存的ArrayList
private final ArrayList<ViewPager.ItemInfo> mItems = new ArrayList();

泛型为ItemInfo:

    static class ItemInfo {Object object; // --->缓存的就是Viewint position;boolean scrolling;float widthFactor;float offset;ItemInfo() {}}

这个ItemInfo类中有众多信息,其中的 Object object 就是专门用来缓存View的。因此,ViewPager才会去缓存界面。仔细看addNewItem方法中的一行代码:

//ItemInfo中的object就是缓存的View
ii.object = this.mAdapter.instantiateItem(this, position);

想想看Adapter调用instantiateItem是干什么的?同时又返回了什么?
在这里插入图片描述这样一来就解释的通了:当需要构建View的时候,addNewItem函数会通过调用Adapter的instantiateItem方法来创建,return的View会被保存到专门用来缓存的ItemInfo的object中。

如果对方是Fragment,那么观察FragmentPagerAdapter:

   @NonNullpublic Object instantiateItem(@NonNull ViewGroup container, int position) {if (this.mCurTransaction == null) {this.mCurTransaction = this.mFragmentManager.beginTransaction();}long itemId = this.getItemId(position);String name = makeFragmentName(container.getId(), itemId);Fragment fragment = this.mFragmentManager.findFragmentByTag(name);if (fragment != null) {this.mCurTransaction.attach(fragment);} else {fragment = this.getItem(position);this.mCurTransaction.add(container.getId(), fragment, makeFragmentName(container.getId(), itemId));}if (fragment != this.mCurrentPrimaryItem) {fragment.setMenuVisibility(false);fragment.setUserVisibleHint(false);}return fragment;}

新建并返回、保存的就是fragment了。至此,ViewPager的缓存原理就十分清晰了。

三、Viewpager+Fragment组合使用

缓存有好处,也有不友好的地方。对Fragment而言,如果不进行懒加载处理,那是非常糟糕的。一般对Fragment进行懒加载处理,不能单一的根据setUserVisibleHint或者onResume来判断。Fragment的界面可见状态分为3种:第一次可见、可见、不可见。这两个函数都不能很好的对其进行精准区分。

在这方面,我们需要关心Fragment的几个生命周期函数:onCreateView、onActivityCreated、onResume、onPause、onDestroyView。

onCreateView,最先想到的就是解析xml布局(这也是最根本的),其次就是初始化控件。
onActivityCreated,表示Activity创建完毕。
onResume、onPause和onDestoryView无需多言,常规认识。

关于setUserVisibleHint,它与Fragment的生命周期无关,仅仅是为了表达页面是否对用户可见。还记得FragmentPagerAdapter吗?这个适配器它内部的setPrimaryItem方法是用来设置当前Item是否可见的,方法内调用的就是setUserVisibleHint(true)方法:
在这里插入图片描述
关于setUserVisibleHint方法修改Fragment可见性,调用场景如下:

  • ① 切换tab时,会优先于所有Fragment生命周期函数调用
  • ② Fragment之前已经调用过该方法,但是后续要让Fragment的状态在可见与不可见之间切换

setUserVisibleHint(false)表示通知Fragment不可见,即终止一切网络请求!但是如果从未创建过就要怎样怎样,那就会报空指针异常。所以需要一个标志位来判断界面是否已经创建。只有当页面被创建出来了,才会去分发可见性。否则xml都还没加载,分发个球?不报空指针才怪呢。

所以,在setUserVisibleHint方法的处理上,我们根本不用考虑isViewCreated==false的情况。当isViewCreated为true时,我们再根据传进来的可见状态与当前页面可见状态,分发可见性。

    @Overridepublic void setUserVisibleHint(boolean isVisibleToUser) {super.setUserVisibleHint(isVisibleToUser);//只考虑xml加载出来的情况if (isViewCreated) {//根据传进来的状态 和 当前页面的可见性,判断分发是否可见if (isVisibleToUser && !currentVisibleState ) {dispatchUserVisibleHint(true);} else if (!isVisibleToUser && currentVisibleState) {dispatchUserVisibleHint(false);}}}

我们通过dispatchUserVisibleHint方法来统一处理用户可见信息的分发,在分发方法中,再区分是否是第一次可见。因为只有当第一次可见时,才会去主动做一些事的。否则其他情况的可见性,就通知用户可见状态,履行onResume()的职责。

当然,这里还需要用到currentVisibleState表示当前页面可见性,借助mIsFirstVisible 标记区分是否是第一次可见。

    private void dispatchUserVisibleHint(boolean isVisible) {//为了代码严谨if (currentVisibleState == isVisible) {return;}currentVisibleState = isVisible;if (isVisible) {if (mIsFirstVisible) {mIsFirstVisible = false;onFragmentFirstVisible();}onFragmentResume();} else {onFragmentPause();}}

另外,当FragmentTransaction来控制fragment的hide和show时,就会调用onHiddenChanged方法。此时,Fragment的生命周期函数不会再执行,任何生命周期都不会再走了(具体原因点击查看)。在这种情况下,数据就不能根据生命周期函数来判断刷新,此时可以依赖onHiddenChanged方法来继续判断处理:

    @Overridepublic void onHiddenChanged(boolean hidden) {super.onHiddenChanged(hidden);if (hidden) {dispatchUserVisibleHint(false);} else {dispatchUserVisibleHint(true);}}

剩下的工作,就是处理边边角角了。在onResume和onPause中根据是否第一次可见、当前页面可见性、getUserVisibleHint等对是否可见、是否第一次可见进行区分,并以此来分发可见性。

当然,如果考虑Fragment内嵌套Fragment,这里还得再多处理一层,那就是对内层Fragment分发可见性。代码不一样,但是性质差不多。首先要判断其Parent是否可见:

    private boolean isParentInvisible() {Fragment parentFragment = getParentFragment();if (parentFragment instanceof LazyFragment) {LazyFragment fragment = (LazyFragment)parentFragment;return !fragment.isSupportVisible();}return false;}

然后对统一分发进行小改,综合考虑Parent之后,再对Child的可见性向下分发:

    private void dispatchChildVisibleState(boolean visible) {FragmentManager fragmentManager = getChildFragmentManager();List<Fragment> fragments = fragmentManager.getFragments();if (fragments != null) {for (Fragment fragment: fragments) {if (fragment instanceof LazyFragment &&!fragment.isHidden() &&fragment.getUserVisibleHint()) {((LazyFragment)fragment).dispatchUserVisibleHint(visible);}}}}
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 学习Python的应用笔记

    Python 学习怎么学习编程问题一:我想用Python人脸识别Python的安装pip命令安装Python 依赖包编写程序人脸识别程序程序的第一步,先完成简单的识别 怎么学习编程 这里只讲使用,不讲语法,额,稍微讲点儿语法。 想自己上大学的时候,大一直接上去就学C语言。然后就被一个问题困…...

    2024/4/16 5:35:17
  2. Springboot通过Jacoco生成测试用例覆盖率报告

    环境搭建主要讲述,jacoco针对于jar服务,统计代码覆盖率并生成报告!准备项目jar包 自己找一个打包好的jar服务,或者从github上down一个Springboot demo项目,自行打包成jar包。说明:下载后将项目打包成jar。(此处通过idea打开项目,下载依赖,然后执行maven 的install即可)…...

    2024/4/26 12:48:25
  3. HTML5 Canvas眨眼睛动画

    效果请看: http://keleyi.com/a/bjad/p9exlcwi.htm 请使用支持HTML5的浏览器查看效果。以下是代码:3 <html>4 <body>5 <canvas width="300" height="300" id="keleyieye" style="background:black"></canvas&g…...

    2024/4/16 5:34:52
  4. 将windows文件转成linux文件

    dos2unix file...

    2024/4/20 13:21:36
  5. 总结MySQL模糊查询

    一、创建表create table student(id char(36) primary key,name varchar(8) not null,age int(3) default 0,mobile char(11),address varchar(150) ); insert into student values (9b4435ec-372c-456a-b287-e3c5aa23dff4,张三,24,12345678901,北京海淀); insert into studen…...

    2024/4/16 5:34:57
  6. order by总结

    先在MySQL数据库里建一个表,并添加几条数据: create table student(id char(36) primary key,name varchar(8) not null,age int(3) default 0,mobile char(11),address varchar(150) ) insert into student values (9b4435ec-372c-456a-b287-e3c5aa23dff4,张三,24,12345678…...

    2024/4/25 13:27:20
  7. mybatis-ResultHandler解析

    概述 结果值的处理相当于参数的处理会复杂一些,负责结果值转换的类是 ResultSetHandler public interface ResultSetHandler {/*** 处理数据集并返回* @param stmt* @param <E>* @return* @throws SQLException*/<E> List<E> handleResultSets(Statement st…...

    2024/5/1 22:04:29
  8. 116.(124)二叉树中的最大路径和

    题目描述:给定一个非空二叉树,返回其最大路径和。本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。示例 1:输入: [1,2,3]1/ \2 3输出: 6示例 2:输入: [-10,9,20,null,null,15,7]-10/ \9 20/ \15 7输出:…...

    2024/5/1 21:26:16
  9. Thinkphp6搭建的基础RABC权限系统,适用所有场景

    JrkAdmin(TP6.0.3版本) —— 你值得信赖的后端开发框架 如果对您有帮助,您可以点右上角 "Star" 支持一下 谢谢!项目介绍 JrkAdmin_Tp6(基础版)是ThinkPHP6.0和layui的快速开发的后台管理系统。 后台采用RABC权限验证,不懂的同学可以查看相关文档 实现管理员管…...

    2024/5/1 22:39:51
  10. Okhttp在4.x手机上报java.lang.ExceptionInInitializerError错

    今天收到运营部提的一个bug 用户下载完app打开就闪退了,用户的手机设备机型【红米 HM NOTE 1S】【系统版本Android 4.4.4】。 错误详细日志如下:根据错误信息看应该是版本问题,查看okhttp文档我项目里面用的是 implementation com.squareup.okhttp3:okhttp:3.13.1根据上面可…...

    2024/4/17 20:55:51
  11. c++继承(八)——虚拟菱形继承(详解)

    上一篇我们提到菱形继承有数据冗余和二义性的问题。我们看下面的代码 class fruit { public:string _name; };class apple :public fruit { protected:int _appleMoney; };class banana :public fruit { protected:int _bananaMoney; };class store :public apple, public bana…...

    2024/5/1 22:44:35
  12. 【文件管理系统】选择与部署

    1.功能1.可以上传和下载文件,并且记录上传的记录、下载记录、修改记录。 2.支持在线预览文件。 3.支持在线编译文件。 4.支持文件/文件夹的复制、删除、重命名、移动、创建等操作。2.方案 通过这个链接看到几个开源方案选择 链接 2.1 onlyoffice 线上实例1.开源的在线文档编辑…...

    2024/4/22 9:46:29
  13. C语言 数组指针,指针数组

    目录作业作业1 不同维数数组和指针数组的传参作业2 单链表复习课堂笔记1.位运算 & | ^ >> << ~2.编译预处理3. 编码规范4.指针5.数组 作业 作业1 不同维数数组和指针数组的传参1 #include <stdio.h>2 3 void print1(char *ptr)4 {5 prin…...

    2024/4/19 13:44:41
  14. Java集合框架-概述

    Java 集合框架 学习目标会使用集合存储数据 遍历集合,取出数据 掌握每种集合的特性学习方法学习顶层!通过顶层接口/抽象类的共性方法,所有子类都可以使用 使用底层!顶层无法创建对象,需要使用具体的实现类创建对象框架图第一章 Collction集合 一种工具,放在java.util包中…...

    2024/4/21 5:44:35
  15. EL&JSTL学习笔记

    主要内容JSP:指令 注释 内置对象MVC开发模式 EL表达式 JSTL标签 三层架构附录:思维导图 JSP指令作用:用于配置JSP页面,导入资源文件 格式: <%@ 指令名称 属性名1=属性值1 属性名2=属性值2 … %><%@ page language="java" contentType="text/html; …...

    2024/4/20 8:40:02
  16. 蓝桥杯单片机——独立按键、矩阵按键

    蓝桥杯单片机硬件基础独立按键 跳线帽需要短接J5口的3和2引脚,按键能使用的仅有第一列(即上图中S4、S5、S6、S7)。当按键按下时,相应的P30-33口输入为低电平,由此编写独立按键扫描函数。 矩阵按键 跳线帽需要短接J5口的1和2引脚,按键能使用16个(即上图中S4-S19)。矩阵按…...

    2024/4/16 5:33:51
  17. Java编码规范总结

    Java编码规范一、编码规范概述二、文件体系结构规则1、文件体系规则(1)java文件目录结构<模块分类目录>action:存放action(控制层\controller)、dao:存放dao(数据层)、form:存放展示层文件、service:存放业务逻辑文件、vo:存放数据对象文件Model:model是数据模…...

    2024/4/16 5:36:08
  18. Vue通信、传值的多种方式

    一、通过路由带参数进行传值①两个组件 A和B,A组件通过query把orderId传递给B组件(触发事件可以是点击事件、钩子函数等)this.$router.push({ path: /conponentsB, query: { orderId: 123 } }) // 跳转到B②在B组件中获取A组件传递过来的参数this.$route.query.orderId 二、通…...

    2024/4/30 21:35:27
  19. 模拟简单的哈希表

    import java.util.Scanner;public class Demo {public static void main(String[] args) {HashTab hashTab = new HashTab(7);Scanner scanner = new Scanner(System.in);String key="";while (true){System.out.println("add 添加");System.out.println(&…...

    2024/4/17 23:23:41
  20. spark 使用

    安装 anaconda 虚拟环境比如:py37 source activate sudo conda install package进入spark的安装目录下,有一个spark-env.sh文件,例如:/opt/spark/spark-2.1.1-bin-hadoop2.7/conf/spark-env.sh,在环境变量中增加PYSPARK_PYTHON,例如添加:export PYSPARK_PYTHON=/home/q/…...

    2024/4/16 5:36:54

最新文章

  1. 虚拟机安装与配置win7

    一、安装镜像 Windows7 64位 ed2k://|file|cn_windows_7_ultimate_with_sp1_x64_dvd_u_677408.iso|3420557312|B58548681854236C7939003B583A8078|/ 建议迅雷下载 二、VMware 安装win7 1.新创自定义虚拟机 2.默认即可 3.iso文件我们自己下载&#xff0c;选择一个空的磁盘 4.…...

    2024/5/1 23:32:57
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 方案分享 | 嵌入式指纹方案

    随着智能设备的持续发展&#xff0c;指纹识别技术成为了现在智能终端市场和移动支付市场中占有率最高的生物识别技术。凭借高识别率、短耗时等优势&#xff0c;被广泛地运用在智能门锁、智能手机、智能家居等设备上。 我们推荐的品牌早已在2015年进入指纹识别应用领域&#xff…...

    2024/5/1 13:00:02
  4. 基于AI智能识别技术的智慧展览馆视频监管方案设计

    一、建设背景 随着科技的不断进步和社会安全需求的日益增长&#xff0c;展览馆作为展示文化、艺术和科技成果的重要场所&#xff0c;其安全监控系统的智能化升级已成为当务之急。为此&#xff0c;旭帆科技&#xff08;TSINGSEE青犀&#xff09;基于视频智能分析技术推出了展览…...

    2024/4/30 17:11:11
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/1 17:30:59
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/30 18:14:14
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/29 2:29:43
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/30 18:21:48
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/30 9:43:09
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/29 20:46:55
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/30 22:21:04
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/1 4:32:01
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/30 9:42:22
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/30 9:43:22
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/30 9:42:49
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57