【Android】基础回顾--四大组件

1. 四大组件是什么?

四大组件:Activity、Service、BroadcastReceiver、ContentProvider。

2. 四大组件的生命周期和简单用法

Activity:

特殊情况下的生命周期:

典型的生命周期好像没什么可说的,主要说一下特殊情况下的生命周期。

  1. 横竖屏的切换

    1. 在横竖屏切换的过程中,会发生Activity被销毁并被重建的过程。

    2. 在了解这种情况下的生命周期,首先应该了解这两个回调:onSaveInstanceState onRestoreInstanceState

    3. 在Activity由于异常情况下终止时,系统会调用 onSaveInstanceState 来保存当前 Activity 的状态。这个方法的调用是在onStop之前,它和onPause没有既定的时序关系,该方法只有在Activity被异常终止的情况下调用。当异常终止的Activity被重建之后,系统会调用onRestoreInstanceState,并且把Activity销毁时onSaveInstanceState 方法所保存的Bundle对象参数同时传递给onRestoreInstanceStateonCreate方法。因为,可以通过onRestoreInstanceState方法来恢复Activity的状态,该方法的调用时机是在onStart之后。其中,onCreateonRestoreInstanceState方法来恢复Activity状态的区别:onRestoreInstanceState回调则表明其中Bundle对象非空,不用加非空判断,而onCreate需要非空判断,建议使用onRestoreInstanceState

横竖屏切换的生命周期:onPause() --> onSaveInstanceState() --> onStop() --> onDestory() --> onCreate() --> onStart() --> onRestoreInstanceState() --> onResume() 
可以通过在AndroidManifest文件的Activity中指定如下属性:
android:configChanges = "orientation| screenSize"
来避免横竖屏切换时,Activity的销毁和重建,而是回调了下面的方法:@Override
public void onConfigurationChanged(Configuration newConfig) {super.onConfigurationChanged(newConfig);
}
  1. 资源内存不足导致优先级低的Activity被杀死

    1. 优先级:前台Activity > 可见但非前台Activity > 后台Activity

启动模式:

Android 提供了四种Activity启动方式:

标准模式:standard

栈顶复用模式:singleTop

栈内复用模式:singleTask

单例模式:singleInstance

  1. 标准模式 standard

    1. 每启动一次Activity,就会创建一个新的Activity实例并置于栈顶。谁启动了这个Activity,那么这个Activity就运行在启动它的那个Activity所在的栈中。

    2. 特殊情况下,如果在Service或Application中启动一个Activity,其并没有所谓的任务栈,可以使用标记位Flag来解决。解决办法:为待启动的Activity指定FLAG_ACTIVITY_NEW_TASK标记位,创建一个新栈。

  2. 栈顶复用模式 singleTop

        @Overrideprotected void onNewIntent(Intent intent) {super.onNewIntent(intent);}
    1. 如果需要新建的Activity位于任务栈栈顶,那么此Activity的实例就不会重建,而是复用栈顶的实例。并回调:

    2. 由于不会重建一个Activity实例,则不会回调其他生命周期方法。

    3. 应用场景:在通知栏点击收到的通知,然后需要启动一个Activity,这个Activity就可以用singleTop,否则每次点击都会新建一个Activity。

  3. 栈内复用模式 singleTask

     
    <activity android:name=".Activity1"android:launchMode="singleTask"android:taskAffinity="com.lvr.task"android:label="@string/app_name"
    </activity>

    1. 该模式是一种单例模式,即一个栈内只有一个该Activity实例。该模式,可以通过在AndroidManifest文件的Activity中指定该Activity需要加载到哪个栈中,即singleTask的Activity可以指定想要加载的目标栈。singleTask和taskAffinity配合使用,指定开启的Activity加入到哪个栈中。

    2. 关于taskAffinity的值:每个Activity都有taskAffinify属性,这个属性指出了它希望进入的Task。如果一个Activity没有显式的指明该Activity的taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果Application也没有指明,那么该taskAffinity的值就等于包名。

    3. 执行逻辑:

      1. 在这种模式下,如果Activity指定的栈不存在,则创建一个栈,并把创建的Activity压入栈内。如果Activity指定的栈存在,如果其中没有该Activity实例,则会创建Activity并压入栈顶,如果其中有该Activity实例,则把该Activity实例之上的Activity杀死清除出栈,重用并让该Activity实例处在栈顶,然后调用onNewIntent()方法。

    4. 应用场景:

      1. 在大多数App的主页,对于大部分应用,当我们在主界面点击返回按钮都是退出应用,那么当我们第一次进入主界面之后,主界面位于栈底,以后不管我们打开了多少个Activity,只要我们再次回到主界面,都应该使用将主界面Activity上所有的Activity移除的方式来让主界面Activity处于栈顶,而不是往栈顶新加一个主界面Activity的实例,通过这种方式能够保证退出应用时所有的Activity都能被销毁。

  4. 单例模式 singleInstance

    1. 作为栈内复用的加强版,打开该Activity时,直接创建一个新的任务栈,并创建该Activity实例放入栈中。一旦该模式的Activity实例已经存在于某个栈中,任何应用在激活该Activity时都会重用该栈中的实例。

    2. 应用场景:呼叫来电界面

特殊情况:前台栈和后台栈的交互

调用SingleTask模式的后台任务栈的Activity,会把整个栈的Activity压入当前栈的栈顶。singleTask会具有clearTop特性,会把之上的栈内Activity清除。

Activity的Flags:

Activity的Flags很多,这里介绍集中常用的,用于设定Activity的启动模式,可以在启动Activity时,通过Intent.addFlags()方法设置。

  1. FLAG_ACTIVITY_NEW_TASK 即 singleTask

  2. FLAG_ACTIVITY_SINGLE_TOP 即 singleTop

  3. FLAG_ACTIVITY_CLEAR_TOP 当他启动时,在同一个任务栈中所有位于它之上的Activity都要出栈。如果和singleTask模式一起出现,若被启动的Activity已经存在栈中,则清除其之上的Activity,并调用该Activity的onNewIntent方法。如果被启动的Activity采用standard模式,那么该Activity连同之上的所有Activity出栈,然后创建新的Activity实例并压入栈中。

Activity的启动过程

应用启动过程

  1. Launcher通过Binder进程间通信机制通知AMS,它要启动一个Activity

  2. AMS通过Binder进程间通信机制通知Launcher进入Paused状态

  3. Launcher通过Binder进程间通信机制通知AMS,它已经准备就绪进入Paused状态,于是AMS就创建一个新的线程,用来启动一个ActivityThread实例,即将要启动的Activity就是在这个ActivityThread实例中运行

  4. ActivityThread通过Binder进程间通信机制将一个ApplicationThread类型的Binder对象传递给AMS,以便以后AMS能够通过这个Binder对象和它进行通信

  5. AMS通过Binder进程间通信机制通知ActivityThread,现在一切准备就绪,它可以真正执行Activity的启动操作了

Service

是Android中实现程序后台运行的解决方案,它非常适用于去执行那些不需要和用户交互而且还要长期运行的任务。Service默认并不会运行在子线程中,它也不运行在一个独立的进程中,它同样执行在UI线程中,因此,不要在Service中执行耗时的操作,除非你在Service中创建了子线程来完成耗时操作。

Service种类划分

按运行地点分类:

类别区别优点缺点应用
本地服务(Local Service)该服务依附在主进程中服务依附于主进程而不是独立的进程,这样在一定程度上节约了资源,因为Local服务是在同一个进程,所以不需要IPC和AIDL。相应bindService会方便很多。主进程被kill后,服务便会终止如:音乐播放等不需要常驻的服务
远程服务(Remote Service)服务为独立的进程,对应进程名格式为所在包名加上你指定的 android:process 字符串。由于是独立的进程,因此在Activity所在进程被kill的时候,该服务依然在运行,不受其他进程影响,有利于为多个进程提供服务具有较高的灵活性。该服务是独立的进程,会占用一定的资源,并且使用AIDL进行IPC稍麻烦一些提供系统服务的Service,这种Service是常驻的

按运行类型分类:

类别区别应用
前台服务会在通知栏显示onGoing的Notification当服务被终止的时候,通知栏的Notification也会消失,这样对于用户有一定的通知作用。常见的如音乐播放服务
后台服务默认的服务即为后台服务,即不会在通知一栏显示onGoing的Notification当服务被终止的时候,用户是看不到效果的。某些不需要运行或者终止提供的服务,如天气更新、日期同步等等

按使用方式分类:

类别区别
startService启动的服务主要用于启动一个服务执行后台任务,不进行通信,停止服务使用stopService
bindService启动的服务启动的服务要进行通信,停止服务使用unbindService
同时使用startService、bindService启动的服务停止服务应同时使用stopService与unbindService
Service生命周期

startService() --> onCreate() --> onStartCommand() --> Service running --> onDestory()

bindService() --> onCreate() --> onBind() --> Service running --> onUnbind() --> onDestory()

onCreate():

系统在Service第一次创建时执行此方法,来执行只运行一次的初始化工作,如果service已经运行,这个方法不会调用。

onStartCommand():

每次客户端调用startService()方法启动该Service都会回调该方法(多次调用),一旦这个方法执行,service就启动并且在后台长期运行,通过调用stopSelf()或stopService()来停止服务。

onBind():

当组件调用bindService()想要绑定到service时,系统调用此方法(一次调用),一旦绑定后,下次在调用bindService()不会回调该方法。在你的实现中,你必须提供一个返回一个IBinder来使客户端能够使用它与service通讯,你必须总是实现这个方法,但是如果你不允许绑定,那么你应返回null

onUnbind():

当前组件调用unbindService(),想要解除与service的绑定时系统调用此方法(一次调用,一旦解除绑定后,下次再调用unbindService()会抛异常)

onDestory():

系统在service不再被使用并且要销毁的时候调用此方法(一次调用)。service应在此方法中释放资源,比如线程,已注册的监听器、接收器等等。

三种情况下Service的生命周期
  1. startService / stopService

    1. 生命周期:onCreate --> onStartCommand --> onDestory

    2. 如果一个Service被某个Activity调用Context.startService 方法启动,那么不管是否有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行,直到被调用stopService,或自身的stopSelf方法。当然如果系统资源不足,Android系统也可能结束服务,还有一种方法可以关闭服务,在设置中,通过应用 --> 找到自己应用 --> 停止。

    3. 注意:

      1. 第一次startService会触发onCreate和onStartCommand,以后在服务运行过程中,每次startService都只会触发onStartCommand

      2. 不论startService多少次,stopService一次就会停止服务

  1. bindService / unbindService

    1. 生命周期:onCreate --> onBind --> onUnbind --> onDestory

    2. 如果一个Service在某个Activity中被调用bindService方法启动,不论bindService被调用几次,Service的onCreate方法只会执行一次,同时onStartCommand方法始终不会调用。

    3. 当建立连接后,Service会一直运行,除非调用unbindService来解除绑定、断开连接或调用该Service的Context不存在了(如Activity被finish --- 即通过bindService启动的Service的生命周期依附于启动它的Context),系统会在这时候自动停止该Service。

    4. 注意:第一次bindService会触发onCreate和inBind,以后在服务运行过程中,每次bindService都不会触发任何回调

  1. 混合型

    1. 当一个Service再被启动(startService)的同时又被绑定(bindService),该Service将会一直在后台运行,不管调用几次,onCreate方法始终只会调用一次,onStartCommand的调用次数与startService调用的次数一致(使用bindService方法不会调用onStartCommand)。同时,调用unBindService将不会停止Service,必须调用stopService或Service自身的stopSelf来停止服务。

三种情况下的应用场景

如果你只是想启动一个后台服务长期进行某项任务,那么使用startService便可以了。

如果你想与正在运行的Service取的联系,那么有两种方法,一种是使用broadcast,另外是使用bindService。前者的缺点是如果交流较为频繁,容易造成性能上的问题,并且BroadcastReceiver本身执行代码的时间是很短的(也许执行到一半,后面的代码便不会执行),而后者则没有这些问题,因此我们肯定选择使用bindService(这个时候便同时使用了startService和bindService了,这在Activity中更新Service的某些运行状态是相当有用的)

如果你的服务只是公开了一个远程接口,供连接上的客户端(Android的Service是C/S架构)远程调用执行方法。这个时候你可以不让服务一开始就运行,而只用bindService,这样在第一次bindService的时候才会创建服务的实例运行它,这会节约很多系统资源,特别是如果你的服务是Remote Service,那么该效果会越明显。

BroadcastReceiver

广播接收器

作用:用于监听 / 接收 应用发出的广播消息,并作出响应

应用场景:

  1. 不同组件之间的通信(包括应用内 / 不同应用之间)

  2. 与Android系统在特定情况下的通信,如当电话呼入时,网络可用时

  3. 多线程通信

实现原理
  • 使用了观察者模式:基于消息的发布/订阅事件模型。

  • 模型中有三个角色:消息订阅者(广播接收者)、消息发布者(广播发布者)和消息中心(AMS,即Activity Manager Service)

  • 原理描述

    • 广播接收者通过Binder机制在AMS注册

    • 广播发送者通过Binder机制向AMS发送广播

    • AMS根据广播发送者要求,在已注册列表中,寻找合适的广播接收者,寻找依据:IntentFilter / Permission

    • AMS将广播发送到合适的广播接收者相应的消息循环队列

    • 广播接收者通过消息循环拿到此广播,并回调onReceive()

  • 注意:广播发送者和广播接收者的执行是异步的,发出去的广播不会关心有没有接收者接收,也不确定接收者何时能接受到。

具体使用

自定义广播接收者BroadcastReceiver
  • 继承至BroadcastReceiver基类

  • 重写onReceiver()方法

  • 广播接收器收到相应广播后,会自动回调onReceiver()方法;一般情况下,onReceiver方法会涉及与其他组件之间的交互,如发送Notification、启动service等等;默认情况下,广播接收器运行在UI线程,因此onReceiver方法不能执行耗时操作,否则可能ANR

广播接收器注册

注册方式分为两种:静态注册和动态注册。

静态注册:

在AndroidManifest.xml里通过标签声明:

 
<receiverandroid:enabled=["true" | "false"]//此broadcastReceiver能否接收其他App的发出的广播//默认值是由receiver中有无intent-filter决定的:如果有intent-filter,默认值为true,否则为falseandroid:exported=["true" | "false"]android:icon="drawable resource"android:label="string resource"//继承BroadcastReceiver子类的类名android:name=".mBroadcastReceiver"//具有相应权限的广播发送者发送的广播才能被此BroadcastReceiver所接收;android:permission="string"//BroadcastReceiver运行所处的进程//默认为app的进程,可以指定独立的进程//注:Android四大基本组件都可以通过此属性指定自己的独立进程android:process="string" >//用于指定此广播接收器将接收的广播类型//本示例中给出的是用于接收网络状态改变时发出的广播<intent-filter><action android:name="android.net.conn.CONNECTIVITY_CHANGE" /></intent-filter>
</receiver>

动态注册:

在代码中通过调用Context的registerReceiver()方法进行动态注册BroadcastReceiver:

 
@Override
protected void onResume() {super.onResume();//实例化BroadcastReceiver子类 &  IntentFiltermBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver();IntentFilter intentFilter = new IntentFilter();//设置接收广播的类型intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);//调用Context的registerReceiver()方法进行动态注册registerReceiver(mBroadcastReceiver, intentFilter);
}//注册广播后,要在相应位置记得销毁广播
//即在onPause() 中unregisterReceiver(mBroadcastReceiver)
//当此Activity实例化时,会动态将MyBroadcastReceiver注册到系统中
//当此Activity销毁时,动态注册的MyBroadcastReceiver将不再接收到相应的广播。
@Override
protected void onPause() {super.onPause();//销毁在onResume()方法中的广播unregisterReceiver(mBroadcastReceiver);
}

注意:

动态广播最好在Activity的onResume()注册,onPause()注销,否则会导致内存泄漏,当然,重复注册和重复注销也不允许。

两种注册方式的区别:

注册方式特点应用场景
静态注册(常驻广播)常驻,不受任何组件的生命周期影响(应用程序关闭后,如果有信息广播来,程序依旧会被系统调用)缺点:耗电、占内存需要时刻监听广播
动态注册(非常驻广播)非常驻,灵活,跟随组件的生命周期变化(组件结束 = 广播结束,在组件结束前,必须移除广播接收器)需要特定时刻监听广播
广播发送者向AMS发送广播
广播的发送
  • 广播是用意图(Intent)标识

  • 定义广播的本质:定义广播所具备的意图(Intent)

  • 广播发送:广播发送者将此广播的意图通过sendBroadcast()方法发送出去

广播的类型

广播的类型主要分为5类:

  • 普通广播(Normal Broadcast)

  • 系统广播(System Broadcast)

  • 有序广播(Ordered Broadcast)

  • 粘性广播(Sticky Broadcast)

  • App应用内广播(Local Broadcast)

普通广播:

即开发者自身定义Intent的广播(最常用),发送广播使用如下:

Intent intent = new Intent();
//对应BroadcastReceiver中intentFilter的action
intent.setAction(BROADCAST_ACTION);
//发送广播
sendBroadcast(intent);
  • 若被注册了的广播接收者中注册时IntentFilter的action与上述匹配,则会接收此广播(即进行回调onReceiver()),如下mBroadcastReceiver则会接收上述广播:

 
<receiver //此广播接收者类是mBroadcastReceiverandroid:name=".mBroadcastReceiver" >//用于接收网络状态改变时发出的广播<intent-filter><action android:name="BROADCAST_ACTION" /></intent-filter>
</receiver>

  • 若发送广播有相应权限,那么广播接收者也需要相应权限

系统广播
  • Android中内置了很多系统广播:只要涉及到手机的基本操作(如开关机、网络状态变化、拍照等等),都会发出相应的广播

  • 每个广播都有特定的IntentFilter(包括具体的action)Android系统广播action如下:

系统操作action
监听网络变化android.net.conn.CONNECTIVITY_CHANGE
关闭或打开飞行模式Intent.ACTION_AIRPLANE_MODE_CHANGED
充电时或电量发生变化Intent.ACTION_BATTERY_CHANGED
电池电量低Intent.ACTION_BATTERY_LOW
电池电量充足(即从电量低变化到饱满时会发出广播)Intent.ACTION_BATTERY_OKAY
系统启动完成后(仅广播一次)Intent.ACTION_BOOT_COMPLETED
按下照相时的拍照按键(硬件按键)时Intent.ACTION_CAMERA_BUTTON
屏幕锁屏Intent.ACTION_CLOSE_SYSTEM_DIALOGS
设备当前设置被改变时(设备语言、设备方向等)Intent.ACTION_CONFIGURATION_CHANGED
插入耳机时Intent.ACTION_HEADSET_PLUG
未正确移除SD卡但已取出来时(正确移除方法:设置SD卡和设备内存--卸载SD卡)Intent.ACTION_MEDIA_BAD_REMOVAL
插入外部存储装置(如SD卡)Intent.ACTION_MEDIA_CHECKING
成功安装APKIntent.ACTION_PACKAGE_ADDED
成功删除APKIntent.ACTION_PACKAGE_REMOVE
重启设备Intent.ACTION_REBOOT
屏幕被关闭Intent.ACTION_SCREEN_OFF
屏幕被打开Intent.ACTION_SCREENT_ON
关闭系统时Intent.ACTION_SHUTDOWN
重启设备Intent.ACTION_REBOOT
  • 注:当使用系统广播时,只需要在注册广播接收者时定义相关的action即可,并不需要手动发送广播,当系统有相关操作时会自动进行系统广播

有序广播
  • 定义:发送出去的广播被接收者按照先后顺序接收,有序是针对广播接收者而言的

  • 广播接收者接收广播的顺序规则(同时面向静态和动态注册的广播接收者)

    • 按照Priority属性值从大到小排序

    • Priority属性相同者,动态注册的广播优先

  • 特点:

    • 接收广播按顺序接收

    • 先接收的广播接收者可以对广播进行截断,即后接收的广播接收者不再接收到此广播

    • 先接收的广播接收者可以对广播进行修改,那么后接收的广播接收者将接收到被修改后的广播

  • 具体使用有序广播的使用过程和普通广播非常类似,差异仅在于广播的发送方式:sendOrderedBroadcast(intent);

APP应用内广播
  • Android中的广播可以跨App直接通信(exported对于有intent-filter情况下默认为true)

  • 冲突可能出现的问题:

    • 其他App针对性发出与当前App intent-filter 相匹配的广播,由此导致当前App不断接收广播并处理;

    • 其他App注册与当前App一致的intent-filter用于接收广播,获取广播具体信息。即会出现安全性&效率性的问题

  • 解决方案 使用App应用内广播(Local Broadcast)

    • App应用内广播可以理解为一种局部广播,广播的发送者和接收者都同属于一个App

    • 相比于全局广播(普通广播),App应用内广播优势体现在:安全性高 & 效率高

  • 具体使用1 将全局广播设置成局部广播

    • 注册广播时将exported属性设置为false,使得非本App内部发出的此广播不被接受

    • 在广播发送和接收时,增设相应权限permission,用于权限验证

    • 发送广播时指定该广播接收器所在的包名,此广播将只会发送到此包中的App内与之相匹配的有效广播接收器中,通过intent.setPackage(packageName)指定包名

  • 具体使用2 使用封装好的LocalBroadcastManager类

  • 使用方式上与全局广播几乎相同,只是注册 / 取消注册广播接收器和发送广播时将参数的context变成了LocalBroadcastManager的单一实例

  • 注:对于LocalBroadcastManager方式发送的应用内广播,只能通过LocalBroadcastManager动态注册,不能静态注册。

  • //注册应用内广播接收器//步骤1:实例化BroadcastReceiver子类 & IntentFilter mBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(); //步骤2:实例化LocalBroadcastManager的实例localBroadcastManager = LocalBroadcastManager.getInstance(this); //步骤3:设置接收广播的类型 intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE); //步骤4:调用LocalBroadcastManager单一实例的registerReceiver()方法进行动态注册 localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter); //取消注册应用内广播接收器localBroadcastManager.unregisterReceiver(mBroadcastReceiver); //发送应用内广播Intent intent = new Intent(); intent.setAction(BROADCAST_ACTION); localBroadcastManager.sendBroadcast(intent);

粘性广播

Android 5.0 & API 21中已经失效

ContentProvider

内容提供者

作用

进程间进行数据交互&共享,即跨进程通信

原理

ContentProvider的底层采用Android中的Binder机制

具体使用

统一资源标识符(RUI)

作用:唯一标识ContentProvider & 其中的数据,外界进程通过URI找到对应的ContentProvider & 其中的数据,再进行数据操作

具体使用:

URI分为系统预置 & 自定义,分别对应系统内置的数据(如通讯录、日程表等等)和自定义数据库。

// 设置URIUri uri = Uri.parse("content://com.carson.provider/User/1")

// 上述URI指向的资源是:名为 com.carson.providerContentProvider 中表名 为User 中的 id为1的数据// 特别注意:URI模式存在匹配通配符* & #// :匹配任意长度的任何有效字符的字符串// 以下的URI 表示 匹配provider的任何内容content://com.example.app.provider/ // #:匹配任意长度的数字字符的字符串// 以下的URI 表示 匹配provider中的table表的所有行content://com.example.app.provider/table/#

MIME数据类型
  • MIME,即多功能Internet邮件扩充服务。它是一种多用途网际邮件扩充协议。MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

  • 作用:指定某个扩展名的文件用某种应用程序来打开。

  • ContentProvider根据URI返回MIME类型

ContentProvider.getType(uri);

  • MIME类型组成

  • 每种MIME类型由两部分组成=类型+子类型

  • MIME类型是一个包含两部分的字符串,例:

  • text / html 类型为text 子类型为html

  • text/css text/xml 等等

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

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

相关文章

基于Datawhale开源量化投资学习指南(11):LightGBM在量化选股中的优化与实战

1. 概述 在前几篇文章中&#xff0c;我们初步探讨了如何通过LightGBM模型进行量化选股&#xff0c;并进行了一些简单的特征工程和模型训练。在这一篇文章中&#xff0c;我们将进一步深入&#xff0c;通过优化超参数和实现交叉验证来提高模型的效果&#xff0c;并最终通过回测分…

C++ | Leetcode C++题解之第516题最长回文子序列

题目&#xff1a; 题解&#xff1a; class Solution { public:int longestPalindromeSubseq(string s) {int n s.length();vector<vector<int>> dp(n, vector<int>(n));for (int i n - 1; i > 0; i--) {dp[i][i] 1;char c1 s[i];for (int j i 1; j…

2-135 基于matlab的有限差分法计算电位分布

基于matlab的有限差分法计算电位分布&#xff0c;设置目标尺寸的矩形区域&#xff0c;设置矩形区域内的网格数量&#xff0c;根据网格位置在区域内设置电位&#xff0c;实现电位分布计算。程序已调通&#xff0c;可直接运行。 下载源程序请点链接&#xff1a;2-135 基于matlab…

微信小程序的日期区间选择组件的封装和使用

组件化开发是一种将大型软件系统分解为更小、更易于管理和复用的独立模块或组件的方法。这种方法在现代软件开发中越来越受到重视&#xff0c;尤其是在前端开发领域。微信小程序的日期区间选择组件的使用 wxml 代码 <view><view bind:tap"chooseData">…

【Redis】内存淘汰策略

文章目录 什么是内存淘汰策略设置Redis最大内存执行内存淘汰策略的流程Redis的八大内存淘汰策略深入源码进行理解内存淘汰策略流程 什么是内存淘汰策略 Redis内存淘汰策略是指当Redis的内存使用达到其配置的最大内存限制&#xff08;maxmemory&#xff09;时&#xff0c;Redis…

论文笔记(五十)Segmentation-driven 6D Object Pose Estimation

Segmentation-driven 6D Object Pose Estimation 文章概括摘要1. 引言2. 相关工作3. 方法3.1 网络架构3.2 分割流3.3 回归流3.4 推理策略 4. 实验4.1 评估 Occluded-LINEMOD4.1.1 与最先进技术的比较4.1.2 不同融合策略的比较4.1.3 与人体姿态方法的比较 4.2 在YCB-Video上的评…

uniapp使用easyinput文本框显示输入的字数和限制的字数

uniapp使用easyinput文本框显示输入的字数和限制的字数 先上效果图&#xff1a; 整体代码如下&#xff1a; <template><view class"nameInfoContent"><uni-easyinput class"uni-mt-5" suffixIcon"checkmarkempty" v-model&quo…

【MyBatis源码】SqlSessionFactoryBuilder源码分析

文章目录 概述类结构从 InputStream 创建 SqlSessionFactoryXMLConfigBuilder构建ConfigurationXMLConfigBuilder初始化方法parse()方法parseConfiguration属性&#xff08;properties&#xff09; 概述 SqlSessionFactory 是 MyBatis 的核心接口之一&#xff0c;提供创建 Sql…

vue通过JSON文件生成WPML文件源码

可以使用封装的json解析器进行JSON数据获取&#xff0c;读取点的经度、维度、高程等数据&#xff0c;再使用对应的WPML文件生成函数使用该源码下载WPML文件&#xff08;固定WPML生成&#xff1a;js模板式生成大疆上云wpml文件&#xff08;含详细注释&#xff0c;已封装成函数&a…

(7) cuda异常处理

文章目录 上节概要异常处理代码 上节概要 上一节 block_width 64的时候&#xff0c;64644096 > 1024&#xff08;一个block里面最多只能有1024个线程&#xff0c;所以这里计算会有问题&#xff09; 异常处理 __FILE__: 编译器内部定义的一个宏。表示的是当前文件的文件…

【C++单调栈 贡献法】907. 子数组的最小值之和|1975

本文涉及的基础知识点 C单调栈 LeetCode907. 子数组的最小值之和 给定一个整数数组 arr&#xff0c;找到 min(b) 的总和&#xff0c;其中 b 的范围为 arr 的每个&#xff08;连续&#xff09;子数组。 由于答案可能很大&#xff0c;因此 返回答案模 109 7 。 示例 1&#x…

项目:Boost 搜索引擎

项目&#xff1a;Boost 搜索引擎 1、项目背景 公司&#xff1a;百度、360、搜狗、谷歌 …站内搜索&#xff1a;搜索的数据更垂直&#xff08;相关&#xff09;&#xff0c;数据量小 2、整体框架 3、技术栈和项目环境 技术栈&#xff1a;C/C C11&#xff0c;STL&#xff0c;jso…

error Unexpected mutation of “xxxxx“ prop

错误是在进行 eslint 检查的时候触发的&#xff0c;这个错误的原因是我们在子组件中改变了父组件传递过来的 props 解决方法一&#xff1a; 不改变父组件传递过来的 props&#xff0c;如果需要改变父组件传递过来的值&#xff0c;可以使用 defineModel() 进行接收值&#xff…

【零售和消费品&软件包】快递包装类型检测系统源码&数据集全套:改进yolo11-HSPAN

改进yolo11-EfficientHead等200全套创新点大全&#xff1a;快递包装类型检测系统源码&#xff06;数据集全套 1.图片效果展示 项目来源 人工智能促进会 2024.10.24 注意&#xff1a;由于项目一直在更新迭代&#xff0c;上面“1.图片效果展示”和“2.视频效果展示”展示的系统…

STM32第15章 RCC-使用HSE/HSI配置时钟

时间:2024.10.21-10.23 参考资料: 《零死角玩转STM32》“RCC-使用HSE/HIS配置时钟”章节 TIPS: 从前面的历程中我们知道,程序在启动的时候会执行汇编文件,汇编文件里会调用System_Init(固件库编程的函数),它里面会把时钟初始化成72M,因此前面我们在用固件库写程序的…

MSR寄存器独有的还是共享的

英特尔白皮书Volume 4: Model-Specific Registers 这一章列出了不同英特尔处理器系列的 MSR&#xff08;模型特定寄存器&#xff09;。所有列出的 MSR 都可以使用 RDMSR 和 WRMSR 指令进行读取和写入。MSR 的作用域定义了访问相同 MSR 的处理器集合&#xff0c;具体如下&#x…

栈和队列(上)-栈

1. 栈的概念 引入: 我们平时拿羽毛球,是从盒子顶部的羽毛球开始拿的,而顶部的元素是我们最后放进去的. 栈: 一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后…

温泉押金原路退回系统, 押金+手牌+电子押金单——未来之窗行业应用跨平台架构

一、温泉手牌收押金必要性 1. 防止手牌丢失&#xff1a;手牌是顾客在温泉内存储个人物品和进出更衣室的重要凭证。收押金可以让顾客更加重视手牌&#xff0c;降低丢失的概率。比如说&#xff0c;有的顾客可能会因为粗心大意随手放置手牌&#xff0c;如果没有押金的约束&…

STM32之外部中断(实验对射式传感器计次实验)

外部中断配置 #include "stm32f10x.h" // Device headeruint16_t CountSensor_Count;void CountSensor_Init(void) {//RCC--> GPIO--> AFIO--> EXTI--> NVIC五步RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启GPIOB时…