AndroidReact-Native为Fresco的初始化提供自定义的Configuration
Posted Sodino
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AndroidReact-Native为Fresco的初始化提供自定义的Configuration相关的知识,希望对你有一定的参考价值。
React-Native
界面在启动时会调用Fresco
的初始化,即如果Fresco
已经初始化过了,也会再重新执行初始化过程一次。
具体调用栈如下:
这会导致原先的Fresco
初始化的配置全部失效,比如缓存大小被改变图片可能过早被清除,失去自定义的NetworkFetcher
导致图片下载失败(如果NetworkFetcher
涉及添加自定义头信息的话)。
该问题在"react-native": "^0.40.0"
中才得以解决。解决办法为MainReactPackage
的构造函数中增加MainPackageConfig
参数,该参数可指定Fresco
的ImagePipelineConfig
。
应该是Fresco
的坑(因为只要Fresco.initialize()
判断避免重复初始化即),可却是React-Native
来填(这也是机缘呀,因为该bug是反馈在React-Native
的issue
上)。
填坑代码:
MyApplication.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | private ImagePipelineConfig imagePipelineConfig; public void onCreate() // .... do something .... initFresco(); .... public void initFresco() DiskCacheConfig diskCacheConfig = DiskCacheConfig.newBuilder( this) .setBaseDirectoryPath( new File(MultiCard.getInstance( this).getRootDir())) .setBaseDirectoryName(MultiCard.FRESCO_IMAGE_CACHE) .setMaxCacheSize( 50 * ByteConstants.MB) .setMaxCacheSizeOnLowDiskSpace( 10 * ByteConstants.MB) .setMaxCacheSizeOnVeryLowDiskSpace( 2 * ByteConstants.MB) .build(); imagePipelineConfig = ImagePipelineConfig.newBuilder( this) .setNetworkFetcher( new MyImageDownloaderFetcher()) .setMainDiskCacheConfig(diskCacheConfig).build(); Fresco.initialize( this, imagePipelineConfig); public ImagePipelineConfig getImagePipelineConfig() return imagePipelineConfig; |
ReactNativeBaseActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | @Override protected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); mReactRootView = new ReactRootView( this); // ↓↓↓ start custom config to fresco MainPackageConfig.Builder configBuilder = new MainPackageConfig.Builder(); configBuilder.setFrescoConfig(myApplication.getImagePipelineConfig()); mReactInstanceManager = ReactInstanceManager.builder() .setApplication(ElnApplication.getInstance()) .setBundleAssetName( "index.android.bundle") .setJSMainModuleName( "index.android") .addPackage( new MainReactPackage(configBuilder.build())) .addPackage( new ModulePackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); // ↑↑↑ end custom config to fresco Bundle bundle = getExtra(); if(bundle == null) bundle = new Bundle(); mReactRootView.startReactApplication(mReactInstanceManager, "MyBoduleName", bundle); setContentView(mReactRootView); |
填坑的前前后后
公司的App
主体仍是原生开发的,但有部分界面使用了React-Native
实现。
事情起因,测试同学提了个bug
,说图片加载随机失败。
好吧,随机失败,尝试一下看能不能找出必定失败的步骤吧。
跟进步骤为:
Charles
抓包,查看图片请求详情。要在手机中安装SSL
证书解决图片的https
链接不可查看的现象。- 抓包发现原本应该
response code
是200
,现在却返回302
,Location
是403 Forbidden
的网页。
由此,是被后台的防盗链识别为非法请求拒绝访问了。查看图片链接的请求头信息,发现User-Agent
和Referer
都没有设置,才导致被判定为非法。
App
使用的的图片框架是Fresco
,为了自定义图片的请求头信息(User-Agent
和Referer
)在Fresco
初始化时设置了自定义的NetworkFetcher
为MyImageDownloaderFetcher
。
发现在抓包为403
时,MyImageDownloaderFetcher
类中相关的日志被没有被打印出来。
这时开始怀疑Fresco
配置失效。
这时开始怀疑Fresco
在某个未知时刻被修改了网络配置。
由于ImagePipelineConfig
只在Fresco.initialize()
才会被调用。
这时开始怀疑Fresco
被重新初始化了。
使用Android Studio
的Find Usages
功能,发现Fresco.initialize()
除了在MyApplication
中由自己主动调用外,还在React-Native
中的FrescoModule
被调用了一次。
则在Debug
的编译环境下,对Fresco.initialize()
设置断点,发现App
启动时正常执行一次,打开React-Native
界面时又执行一次。好了,原因就是这里了,后面的执行把老子的网络配置给冲掉了。
原因找到了,接下来是怎么解决。
第一个思路看有没有现成的接口可以自定义Configuration
,没有!
第二个思路是那就使用Java Reflection
再把被篡改的Configuration
改回来吧!(死脑筋)
然后,lixiaowei
同学说上github/react-native/issue
找找,嗯,发现有人反馈了这个bug
,得升级React-Native
然后就可以按第一个思路来解决了。解决办法就如上了。(死开发,别闷着改代码,多聊天呀…)
Reference Link :
Android: Enable apps to provide a custom configuration to Fresco
以上是关于AndroidReact-Native为Fresco的初始化提供自定义的Configuration的主要内容,如果未能解决你的问题,请参考以下文章
Android react-native 中的 MainActivity 不存在错误
如何在 react-native android 应用程序中显示 GIF?
如何在android react-native中正确添加应用程序图标
错误:无法确定当前字符,它不是 android react-native 中的字符串、数字、数组或对象
将 A 转换为 1 B 转换为 2 ... Z 转换为 26,然后将 AA 转换为 27 AB 转换为 28(Excel 中列引用的列索引)