由一个进度条更新所引发的思考
事情的起因
事情是这样子的,我前阵子在Github上开源了一个Android全量版本更新的框架XUpdate, 受到了大家一致的好评。
但是随着使用者基数的不断增大,中间也暴露了很多问题,其中问的最多的就是:"为啥我的版本更新进度条不显示或者不更新呢?"
出现的问题
如果是我遇到了这个问题,我想我最直接的解决方式就是阅读源码或者打断点、打日志去定位问题了。
为啥别人都可以,而我却不行呢?
然而遗憾的是,我发现很多人出现问题的第一反应就是:这什么破玩意儿,怎么不起作用。然后就开始去百度各种搜,又或者加QQ交流群上来就@我一下,把我整得很懵,具体可参考下图:
image起初对于这类问题,我也是非常苦恼:
-
首先,导致版本更新进度条不显示或者不更新的原因会有很多种情况,上来什么上下文都没有就让我帮忙分析问题,那简直就如同你是单身,却问同样是单身狗的我如何摆脱单身是一个级别的问题,你让我怎么回答你呢?
-
其次,我的很多开源框架都会有丰富的wiki资料,里面会有常见问题一栏,里面都罗列了很多使用者常犯的错误已经解决方法。例如XUpdate,就有一份详细的常见问题 说明,里面就介绍了进度条不更新的原因以及解决方案。但是很遗憾,很多人都选择视而不见。很明显的,答案都给你了,你却不愿意去抄,我是真的无能为力。
-
最后,当问题没有得到解决,绝大多数人会选择默默离开,转身去寻找一个更为适合自己的框架,而另一部分人就没有那么友善了,他会对你的框架进行恶语相向,不断贬低你的框架,搞得一副我欠他的样子...就类似下面这位网友这样:
我的反思
做开源项目这么多年,我一直在思考两个问题:
-
为什么要做开源?
-
怎样才能做好开源?
为什么要做开源
在这里我不得不承认,最初我做开源项目的目的就是想提升自己在行业内的知名度,这样也方便以后找工作。但是随着我的开源项目被越来越多的人认可和使用之后,这种观念就渐渐发生变化了,尤其是当我得知有人通过我的开源框架,在短短几天内就写出了一个商用级的App应用后,我的内心其实是非常喜悦的。
现在的我做开源项目,目的非常纯粹:就是想尽可能地帮助大家更好地进行开发,提升开发的效率和能力,让大家有更多的时间用来学习和生活,而不是在公司无尽地重复搬砖。
但是据我观察,很多人在利用开源项目方面,只是为了解决他们遇到的问题,正所谓拿来主义,他们并不会去对项目的设计结构或者实现原理加以研究和学习,这其实完全背离了我做开源项目的初衷。
我一直强调,会用框架并不代表你掌握了框架。只会用框架而不去学习框架的设计思想和实现原理,那么你就是用得再熟练,框架依旧还是别人的,你依旧还只是个初级开发工程师。
更何况你在完全不了解原理的情况下,就冒然去使用一个框架,那么等以后开发遇到坑了之后你咋办,难道准备继续换框架吗?
所以,我现在还是鼓励我的框架使用者遇到问题自己解决,鼓励他们多看文档、源码,多学习框架中巧妙的设计思想,而不是单纯为了解决问题而解决问题。
怎样才能做好开源
我在做开源之初,犯了一个开源者常犯的一个错误:认知错误!
我天真的认为,我的开源项目使用者都是和自己水平差不多的专业人士,很多行话或者基础知识默认他们都是知道的,因此导致了开源项目初期产生很多漏洞或者描述不清的地方。
就拿我的XUpdate项目来说,三年间我陆陆续续地解了100+的issue,你能相信吗,一个简简单单的Android版本更新我可以处理这么多的问题。
image有一天,一位使用者在qq交流群里面又是上来就直接@我:有下载进度,但是进度条为什么不显示?并且发了自己下载功能的实现逻辑代码如下图:
在这里插入图片描述刚开始看这串代码,我就发现不对劲:这小伙子不讲武德啊,怎么能在子线程里面直接回调进度更新呢,这怕是没写过Android吧...
于是,我直接在群里回了一句"你真的人才,在子线程里面回调",然后就默默打开XUpdate的源码,给所有的回调涉及到UI更新的地方都加了一下线程判断,保证在主线程处理UI。
但是写着写着,我又开始觉得不对劲,如果真是在子线程里处理UI的话,为啥程序没崩呢?
果不其然,我的疑惑是对的。小伙在听取了我的建议:将回调放到了主线程之后,依旧还是不能显示进度条。
看到这儿,直觉告诉我可能和这边的进度回调无关。于是我又重新打开进度条更新的源码,仔细看了一遍之后,然后又对比了他之前发来的代码,我恍然大悟:
image这里handleStart
对应的是下载回调的onStart
,而handleProgress
对应的是下载回调的onProgress
,下载回调接口的完整定义如下:
/**
* 下载回调
*/
interface DownloadCallback {
/**
* 下载之前
*/
void onStart();
/**
* 更新进度
*
* @param progress 进度0.00 - 0.50 - 1.00
* @param total 文件总大小 单位字节
*/
void onProgress(float progress, long total);
/**
* 结果回调
*
* @param file 下载好的文件
*/
void onSuccess(File file);
/**
* 错误回调
*
* @param throwable 错误提示
*/
void onError(Throwable throwable);
}
很明显,这个小伙儿只实现了onProgress
的回调接口,却没有实现onStart
的回调接口,这就导致了handleStart
方法里面的mNumberProgressBar.setVisibility(View.VISIBLE);
一直没有得到执行,而在handleProgress
方法里面又没有对进度条设置显示的方法,所以进度条当然一直不显示啦...
看到这儿,我只想说一句"我大意了,没有闪啊!"。要不是这位小伙儿贴出了他那段骚气的代码,我是怎么也不会想到居然有人会这样写!
吐槽归吐槽,但这里确实有逻辑漏洞,所以还是需要兼容一下的。于是乎我就在更新进度条的地方增加了一层判断:如果进度条当前不在显示,那么就先显示它,再更新进度。代码变动如下:
image在经过这次惨痛的教训之后,让我更加深彻地领悟了一点:你永远都猜想不到电脑的那头是谁,以及如何使用你的开源项目。
为此,我特地为XUpdate 开源项目做了如下改进措施:
- 转变思维,站在小白的角度,重新梳理一下现有的使用文档, 让文档更加简单易懂。
- 编写了一个XUpdate的简化库XUpdateAPI:https://github.com/xuexiangjys/XUpdateAPI ,降低XUpdate的使用难度。
- 陆续做了几期XUpdate相关的教学视频: https://space.bilibili.com/483850585/channel/detail?cid=164280
总结
说了这么多,让我们来简单总结一下我的几点反思:
- 1.我们在使用开源项目的时候,要注重对其设计思想和实现原理加以研究和学习,拒绝拿来主义。
- 2.做开源项目的目的应当是为了学习和交流,帮助更多的人成长,而不是为了自己的一己私利。
- 3.好的开源项目,应当是站在使用者角度去分析和解决问题,脱离使用者的项目终将会被遗弃。
我是xuexiangjys,一枚热爱学习,爱好编程,致力于Android架构研究,开源项目经验分享的技术up主,想要获取更多资讯内容,欢迎搜索我的微信公众号: 【我的Android开源之旅】