dart---flutter---android的框架...
其实还是因为新公司比较闲...
Dart
-
dynamic与Object:
dynamic更像是一种泛式,不属于任何类型,而object则在Dart中属于基类
dynamic的话可能需要注意传入的类型判断,object不用
-
final与const
final和const都只能定义变量一次,不可以再修改值
final修饰的是变量是第一次使用时被初始化,const修饰的是编译时的常量
函数式编程,其实可以看成像js或者rxjava那种,讲一个方法当作对象来传入其他对象中。在dart中方法其实也是一个基本数据类型:Function(感觉上就像kotlin的携程,都是可以理解为回调)
若要让函数当作对象来传递,需要想进行声明typedef(这点又跟c++有点像,c++是传递函数指针,dart传递函数对象)
-
异步 Future和Stream
Future只能接收一次异步的结果,接收到将直接执行下一步,然后结束,而stream可以接受多次
Future有 then ,whenComplete , catchError , wait等关键字,跟rxjava的Observable非常相似的用法
Flutter
Widget
- Widget其实相当于View,只不过在Flutter中,Widget变化将依赖State<Widget>
Android
与JS/H5互相通信的第三方框架JsBridge
利用一个事件总线机制(突然好多东西都用的这种方式,android本身啦,EventBus之类的,可能因为好管理??),
需要先进行一下js->android的转义(通过 java.net.URLEncoder )
每一个url对应一个CallbackFunction,然后再将这些对应关系存在HashMap里
AOP
面向切面编程
- 其实是一种思想,可以简单理解为拦路虎或者斯芬克斯,需要过了考验(也就是AOP切入点)之后,才能继续支持之前的操作
详细的已经有人写了(暂时项目用不上...所以懒...),贴上地址
用于重复点击,业务处理前的校验等一些前置的同步同时在同一线程同一进程下的任务
常用Aspect
线程安全
SparseArray
Gradle
一键打包出release包+360加固签名
若是新建gradle, 记得在app目录下的build.gradle开头做引入
从https://blog.csdn.net/u012999651/article/details/105764812中修改
// 把敏感信息存放到自定义的properties文件中
def propertiesFile = rootProject.file("release.properties")
def properties = new Properties()
properties.load(new FileInputStream(propertiesFile))
ext {
// 签名配置
signing = [keyAlias : "yourKeyAlias",
keyPassword : "yourKeyPassword",
storeFile : "yourStoreFileLocal",
storePassword: "yourStorePassword"
]
// app相关的配置
app = [
//默认release apk的文件路径,因为加固是基于release包的
releasePath : "${project.buildDir}/outputs/apk/release",
//对release apk 加固后产生的加固apk地址
packersPath : "${project.buildDir}/outputs/apk/jiagu"
]
// 360加固配置
packers = [account : properties['JiaguLoginName'], //账号
password : properties['JiaguPwd'], //密码
jarPath : properties['JiaguDir'] //执行命令的jar包路径
]
}
/**
* 360加固,适用于新后台打包
* task名字可以自定义后,通过android_studio创建一个task,两个task同名即可
*/
task yourGradleCustomTaskName{
group 'packers'
dependsOn 'assembleRelease'
doLast {
//删除加固后的渠道包
// deleteFile()
// 寻找打包文件release apk
def releaseFile = findReleaseApk()
if (releaseFile != null) {
println "packers found release apk and start jiagu..."
//执行加固签名
packers360(releaseFile)
//重命名加固后apk
renameOutputApk()
} else {
println 'packers===can\'t find release apk and can\'t excute 360 jiagu'
}
}
}
/**
* 对于release apk 进行360加固
*/
def packers360(File releaseApk) {
println 'packers===beginning 360 jiagu'
def packersFile = file(app["packersPath"])
if (!packersFile.exists()) {
packersFile.mkdir()
}
exec {
// 登录360加固保
executable = 'java'
args = ['-jar', packers["jarPath"], '-login', packers["account"], packers["password"]]
println 'packers===import 360 login'
}
exec {
// 导入签名信息
executable = 'java'
args = ['-jar', packers["jarPath"], '-importsign', signing["storeFile"],
signing["storePassword"], signing["keyAlias"], signing["keyPassword"]]
println 'packers===import 360 sign'
}
exec {
// 查看360加固签名信息
executable = 'java'
args = ['-jar', packers["jarPath"], '-showsign']
println 'packers===show 360 sign'
}
exec {
// 初始化加固服务配置,后面可不带参数
executable = 'java'
args = ['-jar', packers["jarPath"], '-config']
println 'packers===init 360 services'
}
exec {
// 执行加固
executable = 'java'
args = ['-jar', packers["jarPath"], '-jiagu', releaseApk.absolutePath, app["packersPath"], '-autosign']
println 'packers===excute 360 jiagu'
}
println 'packers===360 jiagu finished'
println "packers===360 jiagu path ${app["packersPath"]}"
}
/**
* 寻找本地的release apk
* @return true
*/
def deleteFile() {
delete app["packersPath"]
println 'packers===delete all file'
}
/**
* 创建时间标签
* @return
*/
def createDateTip() {
def date = new Date()
def formattedDate = date.format('yyyyMMddHHmm')
return formattedDate
}
/**
* 首先打一个release包,然后找到当前的文件进行加固
* @return releaseApk
*/
def findReleaseApk() {
def apkDir = file(app["releasePath"])
File releaseApk = apkDir.listFiles().find { it.isFile() && it.name.endsWith(".apk") }
println "packers===find release apk ${releaseApk.name}"
return releaseApk
}
/**
* 重命名打包加固后的apk名称
*/
def renameOutputApk() {
File oldApkDir = file(app["packersPath"])
File oldApk = oldApkDir.listFiles().find { it.isFile() && it.name.contains("jiagu") }
def newName = "app-${android.defaultConfig.versionCode}-${createDateTip()}-release.apk"
println "newName = ${newName}"
copy {
from app["packersPath"] + File.separator + oldApk.name
into app["packersPath"]
rename(oldApk.name, newName)
println "packers===output pacckers ${newName}"
}
File newApk = oldApkDir.listFiles().find { it.isFile() && it.name == newName }
oldApk.delete()
println "packers===output packers renameApk ${newApk.absolutePath}"
}