Koin 是为 Kotlin 开发者提供的一个实用型轻量级依赖注入框架,采用纯 Kotlin 语言编写而成,仅使用功能解析,无代理、无代码生成、无反射。
官网地址
依赖注入好处
和dagger相比
1.添加依赖
// Add Jcenter to your repositories if needed
repositories {
jcenter()
}
dependencies {
// Koin for Android
compile "org.koin:koin-android:$koin_version"
}
2.比如创建一个HelloRepository来提供一些数据:
interface HelloRepository {
fun giveHello(): String
}
class HelloRepositoryImpl() : HelloRepository {
override fun giveHello() = "Hello Koin"
}
3.创建一个presenter类,用来使用这些数据:
class MySimplePresenter(val repo: HelloRepository) {
fun sayHello() = "${repo.giveHello()} from $this"
}
4.编写Koin模块,使用该module函数声明模块。
val appModule = module {
// single instance of HelloRepository
single<HelloRepository> { HelloRepositoryImpl() }
// Simple Presenter Factory
factory { MySimplePresenter(get()) }
}
factory每次Activity需要一个实例时都会创建一个新实例。
single 区别在于其提供的实例是单例的
get()这里的功能是直接检索实例(非延迟)
5.启动koin
现在有了一个模块,只需要在Application里调用startKoin()函数:
class MyApplication : Application(){
override fun onCreate() {
super.onCreate()
// Start Koin
startKoin{
androidLogger()
androidContext(this@MyApplication)
modules(appModule)
}
}
}
6.注入依赖
该MySimplePresenter组件将使用HelloRepository实例创建。用by inject()委托注入器注入它:
class MySimpleActivity : AppCompatActivity() {
// Lazy injected MySimplePresenter
val firstPresenter: MySimplePresenter by inject()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//...
}
}
该by inject()功能使我们能够在Android组件运行时(活动,片段,服务…)中检索Koin实例。
fun <T> method(lock: Lock, body: () -> T): T {
lock.lock()
try {
return body()
} finally {
lock.unlock()
}
}
method(lock, {"我是body方法体"})//lock是一个Lock对象
其实上面调用的方法,在编译时期就会把下面的内容替换到调用该方法的地方,这样就会减少方法压栈,出栈,进而减少资源消耗;
lock.lock()
try {
return "我是body方法体"
} finally {
lock.unlock()
}
也就是说inline关键字实际上增加了代码量,但是提升了性能,而且增加的代码量是在编译期执行的,对程序可读性不会造成影响
例子
定义实现一个扩展函数启动 Activity,一般都需要传 Class
// Function
private fun <T : Activity> Activity.startActivity(context: Context, clazz: Class<T>) {
startActivity(Intent(context, clazz))
}
// Caller
startActivity(context, NewActivity::class.java)
使用 reified,通过添加类型传递简化泛型参数
// Function
inline fun <reified T : Activity> Activity.startActivity(context: Context) {
startActivity(Intent(context, T::class.java))
}
// Caller
startActivity<NewActivity>(context)
startKoin(this, appModule, logger = AndroidLogger(showDebug = BuildConfig.DEBUG))
BeanDefinition
override fun <T> get(parameters: ParameterDefinition): Instance<T> {
val needCreation = instance == null
if (needCreation) {
instance = create(parameters)
}
return Instance(instance as T, needCreation)
}
fun <T> create(parameters: ParameterDefinition): T {
try {
val parameterList = parameters()
val instance = bean.definition.invoke(parameterList) as Any
instance as T //创建参数的实例
return instance
} catch (e: Throwable) {
// ....
}
}
总结
示例代码
在web项目中,记日志是非常重要的。所以,我做的第一件事,就是向log包动手。 和Python相比,log包功能上逊色不少,但它给我们提供了基础的构架,让我们能自己稍微封装下。需求对日志包我的要求很低,只要满足: 1.提供Error,Info方法即可 2.日志按天分割,即每隔一天,把昨天的日志保存为logname.20170823这样的文件代码在原来的基础上,我们在src中创建文件夹logger,在里面创建文件logger.go 现在文件结构如下:src--| handlers--| test--| test.go logger--| logger.go | main.go复制这个文件代码有点长,所以放附录了。 要使用,只需要在main.go里调用:logger.InitLogging("8080",logger.DEBUG) logger.Error("%s%s","hi","myboy")复制然后,在bin文件的同级,手工创建logs文件夹。运行程序,日志功能就开始执行了。 测试了一下效率,在macpr
本文为笔者阅读大量文档和做实验的心得。本文不包含任何认证考试解密内容,如想系统性学习红帽OpenStack,请联系红帽公司培训部门。CL210考试环境 笔者在今年参加了OpenStackCL210培训。但是对培训过程中实验环境的网络拓扑当时没有弄明白,后来看了一些资料,总算有了大概的了解。 书上实验的拓扑图见上图。乍一看,是不是有点复杂? 在实验中,每个人分配了一个台式机,台式机是一个RHEL操作系统。通过里面的KVM虚拟化,虚拟出了两个虚拟机Server-a和Server-b。Server-a有两个网卡:eth1和eth2。后来我们做的事情,是在Server-a上以All-in-one的方式安装OpenStack,第二个实验是将ServerB作为Nova-Compute加入到OpenStack中。 当server-a上的openstack安装好以后,创建的虚拟机实例就是基于serveraRHEL中的KVM做的。也就是说,最终我们创建的openstack实例,实际上的三层嵌套虚拟化。 谈到OpenStack的网络,很多人不是很了解细节,但vSphere的网络大家都比较了解,下
哈喽!各位小伙伴大家好呀!本期给大家介绍一下如何使用邮件客户端收发邮件。其实现在大多数人上班都是使用客户端收发邮件, 只有少部分的人还在使用网页来收发邮件。 这篇文章主要还是写给还在网页发邮件的朋友, 希望你也加入到使用邮件客户端的行列。为啥要用客户端呢? 网页邮箱就算你设置了保存密码, 并把网址保存在了收藏夹, 但是每次打开都需要开浏览器,且浏览器需要一直打开当前页面。网页邮箱好是好,只是毕竟依赖网络, 一旦断网,你就查不了历史的邮件,写不了草稿,也无法定时发送,而客户端会把你的邮件全部下载到本地保存, 随时随地都能查,放在自己硬盘里毕竟会安心点。 还有就是多个邮箱的问题了, 当你有多个邮箱时,每个邮箱都要开一个浏览器页面来收信,真的很占用系统资源。如果是客户端话就方便多了可以同时管理多个邮箱账号, 设置自动启动,自动收信, 新邮件弹出提醒,也可以设置新邮件提示音。大部分的邮箱客户端占用资源都很小,至少比浏览器小,而且还有很多网页邮箱没有的功能,比如附件提醒,你在写信时忘了添加附件,但是你的信中写了“附件”两个字,你在点发送时客户端就会提醒你没有添加附件。 说的再好,不如下载一个客户
原文地址:http://jaysoo.ca/2016/02/28/organizing-redux-application/Asourapplicationsgrow,weoftenfindthatfilestructureandorganizationtobecrucialforthemaintainabilityofapplicationcode. 随着应用程序的增长,通常我们就会发现文件结构和组织对于应用程序代码的可维护性来说就会变得非常重要。WhatIwanttodointhispostistopresentthreeorganizationalrulesthatIpersonallyfollowonmyownprojects.Byfollowingtherules,yourapplicationcodeshouldbeeasiertoreasonabout,andyouwillfindyourselfwastinglesstimeonfilenavigation,tediousrefactoring,andbugfixes. 在这篇文章里,我会介绍自己在项目中亲自实践的三条组
这具体是什么类早已忘却,根据当年的注释里面有如下几个功能:实现float,int,double类型的max,min,abs函数。实现计算圆形面积,球体体积的函数。实现计算矩形面积,长方体的函数。/* 功能:实现MathUtility类 作者:windCoder 日期:2013-11-07 */ #include<iostream> usingnamespacestd; /************************************************************************ 功能:实现float,int,double类型的max,min,abs函数。 ************************************************************************/ classComplex { public: Complex(intaX,intaY,floatiX,floatiY,doublerX,doublerY); Complex(); ~Complex(); intmax(intaX,
【新智元导读】青年魏则西的不幸病逝激起了国内公众对搜索引擎虚假医疗网络广告问题的热议。提到搜索引擎,必须想到谷歌,那么谷歌是如何处理医疗广告的呢,答案是使用机器学习的RankBrain算法。 青年魏则西的不幸病逝,激起了国内公众对搜索引擎虚假医疗网络广告问题的热议。根据《商业价值》微信公众号今日文章《谷歌也曾涉足医疗广告,美国司法是如何监管的呢?》,可以发现在谷歌搜索“滑膜肉瘤”也会出医疗广告,但都有明显的“Ad”标识。同时,与百度相比,谷歌的付费广告并不影响排名。谷歌关于滑膜肉瘤治疗的搜索广告,有明确的广告标志。来源:商业价值 此外,《商业价值》文中提到,根据谷歌的搜索广告政策,要投放药品广告需要获得FDA以及美国药房理事会(NABP)认证。也就是说,只有获得政府审批的正规网上药店、药品与治疗才能在网站投放药品类广告。同时,谷歌的自动广告过滤机制,在很大程度上也能有效杜绝虚假医疗广告出现。根据谷歌发布的报告,他们2015年总计预先屏蔽了7.8亿条违规广告,封杀21.4万家广告商,其中包括1250万条违规的医疗和药品广告,涉及药品未获批准或者虚假误导性宣传等原因。谷歌如何用算法排名据统
陈梦腾讯安全平台部高级安全产品经理【谁坑了创业者的钱2】 创业的路上千难万险,一不留神就会尸骨无存。在过去的十年,腾讯安全积累了丰富对抗经验和方法。然而,我们要如何开放十年的积累,能够为这些优秀的企业做点什么,这就是腾讯安全未来的方向——专业、服务、分享。 █什么是DDoS?“你开了一间饭馆,我花钱雇了很多人冲进你的饭馆,占了你的餐位,纠缠你的服务员,但就是不点吃的。这样一来,真正想消费的顾客进不去,你就没有办法提供服务。”----DDoS 每次讲到DDoS都要重复啰嗦这一段,大家可能都听烦了。那我们就直接进入下一个话题。 █为什么创业者容易成为攻击目标? DDoS发展至今天,他的获利途径可以说是复杂的。而创业者变成主要被攻击的对象之一,主要原因是因为这些企业大多未能构建成熟的防御体系,坏人攻击成本小,而获利途径,大多为商业竞争和敲诈勒索。下面给大家详细介绍。 1、商业恶性竞争 商业竞争在互联网这个万亿市场中尤为激烈。一些行业竞争者甚至为了利益不择手段、不顾法纪,通过DDoS攻击妨碍竞争对手的业务活动,打击对手的声誉,从中获取竞争优势。其中,电商行业和在线游戏行业是重灾区。
一、产品特质决定产品所在行业,所在用户群体,产品本身的规模等等都决定了这个产品特质。1、产品所在领域产品所在行业领域决定了产品市场的大小,切入用户群的规模。产品所在领域的延展性,这些产品本生的领域价值会限制产品极简设计的流程。2、产品经理本生的价值产品经理本生的文艺价值和理性价值决定了产品特质。特别是像马扎、乔布斯这类人,对于极简设计的追求,才完成了强大的产品。小龙哥也是具备这种极简能力设计的产品经理。还有就是本生对于产品敏锐度,产品生活气息等等都会决定产品特质。二、抽象细化场景1、场景穷举设计产品时,会对线上场景和线下场景进行穷举。穷举中,通常去找到主流程。如果有主流程,则去对主流程每一个场景进行穷举。穷举过程中,要对反向的场景也要进行穷举。2、场景梳理穷举场景后,对场景进行梳理。梳理场景过程中,是对于场景思考的细节化。包括该场景是否存在,是否合理?场景下所在的流程,用户需要解决什么问题,在这个问题中,我们应该给予什么样的答案?3、场景细化场景梳理完成后,就是极简设计的点,对场景进行简化。比如,以前线下是微信公众号需要关注,关注完了之后,进入主页,主页有一个推送,然后点击链接进入H5
大家好,又见面了,我是你们的朋友全栈君。 MicrosoftWindows平台中两种最常用的锁定方法为WaitForSingleObject和EnterCriticalSection。WaitForSingleObject是一个过载MicrosoftAPI,可用于检查和修改许多不同对象(如事件、作业、互斥体、进程、信号、线程或计时器)的状态。WaitForSingleObject的一个不足之处是它会始终获取内核的锁定,因此无论是否获得锁定,它都会进入特权模式(环路0)。此API还进入Windows内核,即使指定的超时为0,亦如此。此锁定方法的另一不足之处在于,它一次只能处理64个尝试对某个对象进行锁定的线程。WaitForSingleObject的优点是它可以全局进行处理,这使得此API能够用于进程间的同步。它还具有为操作系统提供锁定对象信息的优势,从而可以实现公平性及优先级倒置。 通过对关键代码段实施EnterCriticalSection和LeaveCriticalSectionAPI调用,可以使用EnterCriticalSection。此API具有WaitForSingleO
/** *@authorEdwinChen * */ //定义节点 classNode{ //存储字符串 charstoreChar; //是否完成单词 booleanisComplete; NodeleftChild,centerChild,rightChild; //构造方法 publicNode(charstoreChar,booleanisComplete){ this.storeChar=storeChar; this.isComplete=isComplete; } } publicclassTernarySearchTree{ //根节点 publicNoderoot; //存储结果 HashSet<String>result=newHashSet<String>(); //递归创建tree publicNodeinsert(Stringword,Nodenode,Integerindex){ if(word==null||"".equals(word)) returnnull; //将word转成char数组 char[]char
1023:Pong’sBirds 时间限制: 1Sec 内存限制: 128MB提交: 94 解决: 21[提交][状态][讨论版] 题目描述 Inordertotrainhisbirds,Pongisholdingacompetitionforthem.(Hehavebirds,doeshe?)Hehave2n birds,sohewanttoholdeliminationseries.Literally,ifn=2andhehas4birdsidentifiedas1,2,3,4,hewouldfirsthold competitionfor1and2,3and4,theonefailswouldbeeliminatedandthenheholdscompetitionforthewinners. Accordingtohislongobservation,foreachpairofbirdsheknowstheprobabilitytowinforeachbird,and
1691:文章评分时间限制:1000ms 内存限制:262144KB提交数:1094 通过数:175【题目描述】 nodgd的文章由$n$个小写英文字母组成。文章的一个子串指的是文章中的一段连续的字母,子串的长度就是这一段的字母个数。nodgd在文章中用了排比、对偶、前后照应之类的手法,所以就有很多个子串是相同或者相近的。为了向大家证明这是一篇好文章,nodgd决定给自己的文章进行评分。nodgd首先确定了一个整数$m$,然后统计出文章中有多少个不相同的长度为$m$的子串,这个数量就是文章的评分。 【输入】 第一行包含两个整数$n,m$,表示文章的长度和需要统计的子串长度。 第二行包含一个长度为$n$的只包含小写字母的字符串。 【输出】 一行一个整数,表示文章的评分。 【输入样例】 53 aaaab复制 【输出样例】 2复制 【提示】【样例解释1】 长度为$3$的子串有$3$个,分别是$aaa,aaa,aab$,其中不同的只有$2$个。 【输入样例2】 93 abcabacba复制
方法一:全局指定 settings.xml(第20行) 1<!--指定本地仓库位置--> 2<localRepository>D:\repository\</localRepository> 3 4<!--指定远程镜像--> 5<mirrors> 6<mirror> 7<id>central</id> 8<mirrorOf>central</mirrorOf> 9<name>aliyunmaven</name> 10<url>https://maven.aliyun.com/repository/central</url> 11</mirror> 12<mirror> 13<id>apache.snapshots.https</id> 14<mirrorOf>apache.snapshots.https</mirrorOf> 15<
ClickHouse使用操作 这章主要介绍在ClickHouse使用的各个操作的注意点。常规的统一语法不做详细介绍。 1.Join操作 在ClickHouse中,对连接操作定义了不同的精度,包含ALL、ANY和ASOF三种类型,默认为ALL。可以通过join_default_strictness配置修改默认精度(位于system.setting表中)。下面分别说明这3种精度。 首先建表并插入测试数据: --表join_tb1 CREATETABLEjoin_tb1 ( `id`String, `name`String, `time`DateTime ) ENGINE=MergeTree PARTITIONBYtoYYYYMM(time) ORDERBYid --表join_tb2 CREATETABLEjoin_tb2 ( `id`String, `rate`UInt8, `time`DateTime ) ENGINE=MergeTree PARTITIONBYtoYYYYMM(time) ORDERBYid --表join_tb3 CREATETABLEjoin_
推荐:https://www.zhihu.com/question/19866767 三者是目前市场占有率最高(依安装量而非收入)的关系数据库,而且很有代表性。排行第四的DB2(属IBM公司),与Oracle的定位和架构非常相似,就不赘述了。 如果要说明三者的区别,首先就要从历史入手。 Oracle 中文译作甲骨文,这是一家传奇的公司,有一个传奇的大老板LarryEllision。Ellision32岁还一事无成,读了三个大学,没得到一个学位文凭,换了十几家公司,老婆也离他而去。开始创业时只有1200美元,却使得Oracle公司连续12年销售额每年翻一番。 Oracle成立于1977年,早期的理论基础,反而来自于一篇IBM的论文《ARelationalModelofDataforLargeSharedDataBanks》【1】。作者CODD选取了关系代数的五种运算,并基于运算,架构了一种新型的数据存储模型。基于这种模型,Oracle成为了一个非常典型的关系数据库。因此也变的严谨、安全、高速、稳定,并且变的越来越庞大。 由于其诞生早、结构严谨、高可用、高性能等特点,使其在传统数据库应用中
链接:http://acm.hdu.edu.cn/showproblem.php?pid=3416 题意:starvae在城市A,要去城市B约妹子,要走最短路,并且每段路只能走一次,不能重复走。 题解:在走最短路的情况下,有多少条路从A到B,并且每条路是不重复的(路上经过的任何一条边都不可以重复)。首先是求最短路,然后根据所求的最短路找到这写最短路上的边,将这些边建图,求一次最大流。因为边只能走一次,所以每条边的容量是1,不用拆点(因为城市可以多次经过)。 代码: #include<stdio.h> #include<algorithm> #include<math.h> #include<string.h> #include<vector> #include<queue> #include<map> #include<stack> #include<iostream> #definepiacos(-1.0) #defineINF0x3f3f3f3f usingnamespac
1.3306端口是不是没有打开? 使用nestat命令查看3306端口状态: ~#netstat-an|grep3306复制 tcp 0 0127.0.0.1:3306 0.0.0.0:* LISTEN 从结果可以看出3306端口只是在IP127.0.0.1上监听,所以拒绝了其他IP的访问。 解决方法:修改/etc/mysql/my.cnf文件。打开文件,找到下面内容: #Insteadofskip-networkingthedefaultisnowtolistenonlyon #localhostwhichismorecompatibleandisnotlesssecu