dart---flutter---android的框架...
其實(shí)還是因為新公司比較閑...
Dart
-
dynamic與Object:
dynamic更像是一種泛式偷仿,不屬于任何類型共耍,而object則在Dart中屬于基類
dynamic的話可能需要注意傳入的類型判斷,object不用
-
final與const
final和const都只能定義變量一次葫录,不可以再修改值
final修飾的是變量是第一次使用時被初始化,const修飾的是編譯時的常量
函數(shù)式編程吴超,其實(shí)可以看成像js或者rxjava那種奴烙,講一個方法當(dāng)作對象來傳入其他對象中。在dart中方法其實(shí)也是一個基本數(shù)據(jù)類型:Function(感覺上就像kotlin的攜程蜕煌,都是可以理解為回調(diào))
若要讓函數(shù)當(dāng)作對象來傳遞派阱,需要想進(jìn)行聲明typedef(這點(diǎn)又跟c++有點(diǎn)像,c++是傳遞函數(shù)指針斜纪,dart傳遞函數(shù)對象)
-
異步 Future和Stream
Future只能接收一次異步的結(jié)果贫母,接收到將直接執(zhí)行下一步,然后結(jié)束盒刚,而stream可以接受多次
Future有 then 腺劣,whenComplete , catchError 因块, wait等關(guān)鍵字橘原,跟rxjava的Observable非常相似的用法
Flutter
Widget
- Widget其實(shí)相當(dāng)于View,只不過在Flutter中涡上,Widget變化將依賴State<Widget>
Android
與JS/H5互相通信的第三方框架JsBridge
利用一個事件總線機(jī)制(突然好多東西都用的這種方式,android本身啦趾断,EventBus之類的,可能因為好管理吩愧?芋酌?),
需要先進(jìn)行一下js->android的轉(zhuǎn)義(通過 java.net.URLEncoder )
每一個url對應(yīng)一個CallbackFunction,然后再將這些對應(yīng)關(guān)系存在HashMap里
AOP
面向切面編程
- 其實(shí)是一種思想雁佳,可以簡單理解為攔路虎或者斯芬克斯脐帝,需要過了考驗(也就是AOP切入點(diǎn))之后,才能繼續(xù)支持之前的操作
詳細(xì)的已經(jīng)有人寫了(暫時項目用不上...所以懶...)甘穿,貼上地址
用于重復(fù)點(diǎn)擊腮恩,業(yè)務(wù)處理前的校驗等一些前置的同步同時在同一線程同一進(jìn)程下的任務(wù)
常用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相關(guān)的配置
app = [
//默認(rèn)release apk的文件路徑,因為加固是基于release包的
releasePath : "${project.buildDir}/outputs/apk/release",
//對release apk 加固后產(chǎn)生的加固apk地址
packersPath : "${project.buildDir}/outputs/apk/jiagu"
]
?
// 360加固配置
packers = [account : properties['JiaguLoginName'], //賬號
password : properties['JiaguPwd'], //密碼
jarPath : properties['JiaguDir'] //執(zhí)行命令的jar包路徑
]
}
?
/**
* 360加固,適用于新后臺打包
* task名字可以自定義后温兼,通過android_studio創(chuàng)建一個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..."
//執(zhí)行加固簽名
packers360(releaseFile)
//重命名加固后apk
renameOutputApk()
} else {
println 'packers===can\'t find release apk and can\'t excute 360 jiagu'
}
}
}
?
/**
* 對于release apk 進(jìn)行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 {
// 導(dǎo)入簽名信息
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 {
// 初始化加固服務(wù)配置,后面可不帶參數(shù)
executable = 'java'
args = ['-jar', packers["jarPath"], '-config']
println 'packers===init 360 services'
}
exec {
// 執(zhí)行加固
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'
}
?
/**
* 創(chuàng)建時間標(biāo)簽
* @return
*/
def createDateTip() {
def date = new Date()
def formattedDate = date.format('yyyyMMddHHmm')
return formattedDate
}
?
/**
* 首先打一個release包,然后找到當(dāng)前的文件進(jìn)行加固
* @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}"
}