分类 Android开发 下的文章

在使用Flutter开发过程中,我们经常会遇到需要切换版本的时候,而且flutter切换channel后需要重新下载大量内容,每个channel切换完成后需要再跑flutter doctor,又会有大量的下载,而且还都是国外服务器,下载非常慢。

于是尝试着寻找一款合适的工具,原则是可以跨平台,最好是Golang开发的,很巧的是发现 https://blog.befovy.com/2019/12/fvm-using-go/ 这位Golang博主已经开发完成了,github链接在此,主要的思路与使用Dart编写的fvm异曲同工。

安装

由于我是使用Mac电脑的,所以直接使用brew安装

brew tap befovy/taps
brew install fvm

fvm支持导入已有的SDK,由于我之前安装的是stable的channel,所以使用如下命令:

fvm import stable

等待几分钟后即可全部导入完成。

环境变量配置

在使用fvm之前,实际上我已经手动安装过Flutter,所以需要重新修改下环境变量地址,fvm的默认安装路径如下:

export FLUTTER_PATH=~/Library/Application\ Support/fvm/current
export PATH=$PATH:$FLUTTER_PATH/bin

需要根据自己的电脑终端情况,把上述代码拷贝到.bash_profile或者.zshrc文件。

安装指定版本

如果之前未安装其他版本,需要先安装,例如我安装“1.17.5”版本:

fvm install 1.17.5
# 或者
fvm install 1.17.5 --repo https://mirrors.tuna.tsinghua.edu.cn/git/flutter-sdk.git

上述带--repo表示指定路径,推荐使用国内清华镜像加速下载,不过我在实际使用中出现过下列问题:

fvm: Command 'git' exited with error: chdir ~/Library/Application Support/fvm/versions/1.17.5: no such file or directory

结果去掉--repo就正常下载了,如果遇到类似的问题,可以带和不带--repo都试下,我遇到的就是不带是OK的。

使用指定版本

安装好指定版本以后,可以直接使用use命令来使用:

fvm use 1.17.4
flutter doctor

在平时的面试或者开发过程中,经常遇到一个词汇:“依赖注入”,这个其实是一个编程的高级用法,跟这个词关联的设计思想就是IoC(Inversion of Control)设计原则。

IoC中文名为控制反转,在Java开发中,IoC意味着将你设计好的类交给系统去控制,而不是在你的类内部控制,这就存在控制权的对调,所以称为控制反转。

举个形象的栗子:

假设我们设计一辆汽车:先设计轮子,然后根据轮子大小设计底盘,接着根据底盘设计车身,最后根据车身设计好整个汽车。这里就出现了一个“依赖”关系:汽车依赖车身,车身依赖底盘,底盘依赖轮子。

这样的设计看起来没问题,但是可维护性却很低。假设设计完工之后,上司却突然说根据市场需求的变动,要我们把车子的轮子设计都改大一码。这下我们就蛋疼了:因为我们是根据轮子的尺寸设计的底盘,轮子的尺寸一改,底盘的设计就得修改;同样因为我们是根据底盘设计的车身,那么车身也得改,同理汽车设计也得改——整个设计几乎都得改!

我们现在换一种思路。我们先设计汽车的大概样子,然后根据汽车的样子来设计车身,根据车身来设计底盘,最后根据底盘来设计轮子。这时候,依赖关系就倒置过来了:轮子依赖底盘, 底盘依赖车身, 车身依赖汽车。

这时候,上司再说要改动轮子的设计,我们就只需要改动轮子的设计,而不需要动底盘,车身,汽车的设计了。这就是依赖倒置原则——把原本的高层建筑依赖底层建筑“倒置”过来,变成底层建筑依赖高层建筑。高层建筑决定需要什么,底层去实现这样的需求,但是高层并不用管底层是怎么实现的。这样就不会出现前面的“牵一发动全身”的情况。

再来个栗子:

假设我们要设计一个Girl和一个Boy类,其中Girl有kiss方法,即Girl想要Kiss一个Boy。那么,我们的问题是,Girl如何能够认识这个Boy?

在我们中国,常见的MM与GG的认识方式有以下几种:

1、青梅竹马:
Girl从小就知道自己的Boy。

public class Girl {  
    void kiss(){
       Boy boy = new Boy();
    }
}

然而从开始就创建的Boy缺点就是无法在更换。并且要负责Boy的整个生命周期。如果我们的Girl想要换一个怎么办?(笔者严重不支持Girl经常更换Boy)

2、亲友介绍:
由中间人负责提供Boy来见面。

public class Girl {
    void kiss(){
       Boy boy = BoyFactory.createBoy();      
    }
}

亲友介绍,固然是好。如果不满意,尽管另外换一个好了。但是,亲友BoyFactory经常是以Singleton的形式出现,不然就是,存在于Globals,无处不在,无处不能。实在是太繁琐了一点,不够灵活。我为什么一定要这个亲友掺和进来呢?为什么一定要付给她介绍费呢?万一最好的朋友爱上了我的男朋友呢?

3、父母包办:
一切交给父母,自己不用费吹灰之力,只需要等着Kiss就好了。

public class Girl {
    void kiss(Boy boy){
       // kiss boy  
      boy.kiss();
    }
}

Well,这是对Girl最好的方法,只要想办法贿赂了Girl的父母,并把Boy交给他。那么我们就可以轻松的和Girl来Kiss了。看来几千年传统的父母之命还真是有用哦。至少Boy和Girl不用自己瞎忙乎了。

这就是IoC,将对象的创建和获取提取到外部,将自己的需求表达出去,将控制权反转,实现上层对下层的“控制”。

在实际开发过程中,肯定会涉及到类与类之间的依赖,如果直接new Object出来就会出现耦合的问题,特别是涉及到跨组件的开发,有时候一个组件的功能依赖另一个组件,但我们实际上并不太想让组件之间有过多的耦合,那么这时候IoC的思想就有很大的用处了。

参考链接:https://www.zhihu.com/question/23277575/answer/169698662
参考链接:http://www.nowamagic.net/librarys/veda/detail/393

最近在编译项目的过程中,发现R文件不能正常链接,但正常编译可以通过,所有的R文件被标红了,点击会提示 Cannot resolve symbol’R’,但我寻找到R文件的目录,发现R文件确实真实存在,一开始怀疑是公司加密的问题,但后来发现用notepad是可以正常打开R.java文件,所以基本上排除加密问题。

通过Google,找了几篇博文,终于找到原因了,原因是Intellij IDEA对单个文件的大小默认限制为2500KB, Android Studio是基于Intellij IDEA的,而R文件是由编辑器自动生成的,当项目到一定的级别以后,R文件就会超过2500KB的限制,所以最后就出现了开头说的问题。

解决方案如下:

1、进入“Android Studio安装目录\bin\”,找到 idea.properties 文件,找到 idea.max.intellisense.filesize 这一项,这一项就是限制的大小,默认是2500,更改为5000,重启Android Studio即可。

Android Studio版本更新至3.0后,连带的gradle的版本也升级到3.0以上,再使用compile依赖系统会有提示,告诉你不要在用compile。

之前在gradle 3.0以下版本依赖的声明写法是:

compile fileTree(dir: 'libs', include: ['*.jar'])

但在gradle 3.0后的写法是:

implementation fileTree(dir: 'libs', include: ['*.jar'])

api fileTree(dir: 'libs', include: ['*.jar'])

那么这几个的区别是啥?

api
完全等同于compile指令,没区别,你将所有的compile改成api,完全没有错。

implement
这个指令的特点就是,对于使用了该命令编译的依赖,对该项目有依赖的项目将无法访问到使用该命令编译的依赖中的任何程序,也就是将该依赖隐藏在内部,而不对外部公开。

最近在一个项目中使用统一资源定位符的时候,出现一个很诡异的问题,同样的代码,同样的资源放在两个不同的项目工程里,有一个工程正常运行,另一个工程运行异常,报ClassNotFoundException,具体问题和原因,我慢慢道来。

说一下项目使用的场景,有一个html文件需要国际化,所以把该html文件从assets文件夹移动到raw文件夹,并添加了国际化支持,在其中一个项目中完美运行,经过测试js也能成功调用,符合我的使用要求,于是理所当然的移植到另一个项目中,原本以为也会顺利运行,哪晓得打开后,给我一个大大的ERR_FILE_NOT_FOUND,立马打开Logcat,看到以下报错信息:

AndroidProtocolHandler: Unable to open resource URL: file:///android_res/raw/error.html
java.lang.ClassNotFoundException: 
Didn't find class "aaa.bbb.ccc.ddd.eee.R$raw" on path: 
DexPathList[[zip file "/data/app/aaa.bbb.ccc.ddd-1/base.apk"],
nativeLibraryDirectories=[/data/app/aaa.bbb.ccc.ddd-1/lib/arm64, 
/system/lib64, /vendor/lib64]]                                                                                       
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)

开始排查是不是路径错误、是不是构建混淆问题,但排查的结果是两边几乎完全一致,没有这些问题,当时我是懵逼的,随后我就去打了一杯水,慢慢的把目光望向窗外,看到门口地铁施工工地龙门吊上醒目地“勇于跨越,追求卓越”8个大字,于是回来仔细的又看来一遍代码和Logcat日志,于是发现了一个奇怪的地方:

报错的R文件跟我实际使用的R文件不一致,因为manifest里面的包名和applicationId不一致,导致通过统一资源定位符无法找到我的那个文件,需要修改manifest里面的包名与applicationId一致,这样就可以顺利找到raw文件。