7

由一个进度条更新所引发的思考

 3 years ago
source link: https://segmentfault.com/a/1190000039157743
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

事情的起因

事情是这样子的,我前阵子在Github上开源了一个Android全量版本更新的框架 XUpdate , 受到了大家一致的好评。

但是随着使用者基数的不断增大,中间也暴露了很多问题,其中问的最多的就是:"为啥我的版本更新进度条不显示或者不更新呢?"

出现的问题

如果是我遇到了这个问题,我想我最直接的解决方式就是阅读源码或者打断点、打日志去定位问题了。

为啥别人都可以,而我却不行呢?

然而遗憾的是,我发现很多人出现问题的第一反应就是:这什么破玩意儿,怎么不起作用。然后就开始去百度各种搜,又或者加QQ交流群上来就@我一下,把我整得很懵,具体可参考下图:

IBNvMz2.png!mobile

起初对于这类问题,我也是非常苦恼:

  • 首先,导致版本更新进度条不显示或者不更新的原因会有很多种情况,上来什么上下文都没有就让我帮忙分析问题,那简直就如同你是单身,却问同样是单身狗的我如何摆脱单身是一个级别的问题,你让我怎么回答你呢?
  • 其次,我的很多开源框架都会有丰富的wiki资料,里面会有常见问题一栏,里面都罗列了很多使用者常犯的错误已经解决方法。例如XUpdate,就有一份详细的 常见问题 说明,里面就介绍了进度条不更新的原因以及解决方案。但是很遗憾,很多人都选择视而不见。很明显的,答案都给你了,你却不愿意去抄,我是真的无能为力。
  • 最后,当问题没有得到解决,绝大多数人会选择默默离开,转身去寻找一个更为适合自己的框架,而另一部分人就没有那么友善了,他会对你的框架进行恶语相向,不断贬低你的框架,搞得一副我欠他的样子...就类似下面这位网友这样:

U7rQ7rU.png!mobile

我的反思

做开源项目这么多年,我一直在思考两个问题:

  • 为什么要做开源?
  • 怎样才能做好开源?

为什么要做开源

在这里我不得不承认,最初我做开源项目的目的就是想提升自己在行业内的知名度,这样也方便以后找工作。但是随着我的开源项目被越来越多的人认可和使用之后,这种观念就渐渐发生变化了,尤其是当我得知有人通过我的开源框架,在短短几天内就写出了一个商用级的App应用后,我的内心其实是非常喜悦的。

现在的我做开源项目,目的非常纯粹:就是想尽可能地帮助大家更好地进行开发,提升开发的效率和能力,让大家有更多的时间用来学习和生活,而不是在公司无尽地重复搬砖。

但是据我观察,很多人在利用开源项目方面,只是为了解决他们遇到的问题,正所谓拿来主义,他们并不会去对项目的设计结构或者实现原理加以研究和学习,这其实完全背离了我做开源项目的初衷。

我一直强调, 会用框架并不代表你掌握了框架 。只会用框架而不去学习框架的设计思想和实现原理,那么你就是用得再熟练,框架依旧还是别人的,你依旧还只是个初级开发工程师。

更何况你在完全不了解原理的情况下,就冒然去使用一个框架,那么等以后开发遇到坑了之后你咋办,难道准备继续换框架吗?

所以,我现在还是鼓励我的框架使用者遇到问题自己解决,鼓励他们多看文档、源码,多学习框架中巧妙的设计思想,而不是单纯为了解决问题而解决问题。

怎样才能做好开源

我在做开源之初,犯了一个开源者常犯的一个错误:认知错误!

我天真的认为,我的开源项目使用者都是和自己水平差不多的专业人士,很多行话或者基础知识默认他们都是知道的,因此导致了开源项目初期产生很多漏洞或者描述不清的地方。

就拿我的XUpdate项目来说,三年间我陆陆续续地解了100+的issue,你能相信吗,一个简简单单的Android版本更新我可以处理这么多的问题。

fq2mAjr.png!mobile

有一天,一位使用者在qq交流群里面又是上来就直接@我:有下载进度,但是进度条为什么不显示?并且发了自己下载功能的实现逻辑代码如下图:

NnyMFnI.png!mobile

刚开始看这串代码,我就发现不对劲:这小伙子不讲武德啊,怎么能在子线程里面直接回调进度更新呢,这怕是没写过Android吧...

于是,我直接在群里回了一句"你真的人才,在子线程里面回调",然后就默默打开XUpdate的源码,给所有的回调涉及到UI更新的地方都加了一下线程判断,保证在主线程处理UI。

但是写着写着,我又开始觉得不对劲,如果真是在子线程里处理UI的话,为啥程序没崩呢?

果不其然,我的疑惑是对的。小伙在听取了我的建议:将回调放到了主线程之后,依旧还是不能显示进度条。

看到这儿,直觉告诉我可能和这边的进度回调无关。于是我又重新打开进度条更新的源码,仔细看了一遍之后,然后又对比了他之前发来的代码,我恍然大悟:

vMrqEv3.png!mobile

这里 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 方法里面又没有对进度条设置显示的方法,所以进度条当然一直不显示啦...

看到这儿,我只想说一句"我大意了,没有闪啊!"。要不是这位小伙儿贴出了他那段骚气的代码,我是怎么也不会想到居然有人会这样写!

吐槽归吐槽,但这里确实有逻辑漏洞,所以还是需要兼容一下的。于是乎我就在更新进度条的地方增加了一层判断:如果进度条当前不在显示,那么就先显示它,再更新进度。代码变动如下:

6NNnIbJ.png!mobile

在经过这次惨痛的教训之后,让我更加深彻地领悟了一点:你永远都猜想不到电脑的那头是谁,以及如何使用你的开源项目。

为此,我特地为 XUpdate 开源项目做了如下改进措施:

总结

说了这么多,让我们来简单总结一下我的几点反思:

  • 1.我们在使用开源项目的时候,要注重对其设计思想和实现原理加以研究和学习,拒绝拿来主义。
  • 2.做开源项目的目的应当是为了学习和交流,帮助更多的人成长,而不是为了自己的一己私利。
  • 3.好的开源项目,应当是站在使用者角度去分析和解决问题,脱离使用者的项目终将会被遗弃。

我是xuexiangjys,一枚热爱学习,爱好编程,致力于Android架构研究,开源项目经验分享的技术up主,想要获取更多资讯内容,欢迎搜索我的微信公众号: 【我的Android开源之旅】


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK