写在2017年的开始,2016的结束

又到了春节放假前,工作任务已经完成,处于无所事事的状态中了,不幸的是还有4天才放假…

如何愉快的度过这几天呢?突然想到了最近一直思考的问题:写了这么多年的程序,到底留下了什么?

还记得上一次更新自己的个人简历还是2014年,从自己2007年开始工作,写windows c++、linux c++,

后来移动APP崛起,找本书看看就开始obj-c、android,直到现在接触python、javascript,才开始写自己的blog网站。

关键字:
1、沉淀
就像建筑工人盖房子一样,房子是劳动的结晶,工人在这个过程中,熟练了工艺、积累了经验、收获了成就。

软件工程虽然可以类比,但实际上生产工具也是开发者创造的,而且在不断的更新换代,对开发者有持续不断的学习压力。甚至,有些技术

会过时、公司会砍掉等等,那么如何让我这样的巨蟹男增强点信心…沉淀,或许是最好的结果。不紧紧是记录过程,也不是源代码,这些都会遗忘,

能保留的,也许只有当前的自我意识和习惯行为,所以我想把这些模糊的问题,结合某些灵光一闪的思路,来寻找出解决的方案。

理论上来说,应该给大脑划分能力区域,建立操作系统级别的应对框架,依附于坚实的骨架上的血肉,才可以自由的扩展。

任何新知识都源于初级定义+逻辑组织,能力也不例外,是根据旧有认知(定义+逻辑框架),对未知事物的反馈结果。

从婴儿时代,一张白纸开始,懵懂的自我意识,围绕着五感,建立了初级的人行自走计算机。。。这个过程大概沉淀的是单纯的输入-》输出、记忆存储。

接着小学-》初中-》高中,是有针对性的,通过学习,来建立、强化各种认知,以及训练和扩展脑容量的过程,伴随着身体的成熟,让简单的意识,

点燃了智慧,形成各种逻辑回路;当然了,像我这样的,情商压根就没进化,只进化了智商,也是缺少部分成长的指引。这个过程,我认为是认知对象化。

大学时代,是自由生长的阶段,解放了少年人的心性,是认知爆炸-》循环-》再认知,拥有着一生中最快的反应速度以及接受新观点、思维最活跃的黄金时代。

虽然是最好的时期,却因为不成熟,很容易就歪掉了,自我引导,也许是这阶段的目的,也是沉淀的终极目的。例如,想玩游戏了,不去上课,这是最常见的问题。

步入工作了,无非是工作熟练的过程,还有一个创造力的问题;一般人按图索骥,也能混得不错;有创造力的人,总是让人眼前一亮,这东西还能这样玩!我认为,

这两者的差距之所以天差地别的原因,在于沉淀,思考的多了,从简单-》复杂-》抽象简化-》返璞归真,看似相似的东西,因为人的加工、雕琢,才达到大成。

我认为这里,沉淀的是底蕴,是善于思考,是深入骨髓的、是夜深人静时刻独自静思的升华。各种技术手段、各种语言平台,都有自己的脉络,你不会,是因为你

缺少某些前置知识的认知过程,在全栈工程师眼里,只有分工不同,没有不能融洽的地方。都说四十才是真正的程序员,挺有道理的,写的代码多了,接触不同的

技术多了,融会贯通,是我目前这个阶段的目的,也是沉淀的目标。程序员的世界总是那么简单,而生活却那么复杂,看来是缺少了情商组件……

2、钱
挣钱如何成为兴趣的附加品
关于如何挣钱,很难啊,因为我也只吃一口饭。可是我是搞软件的,随便整点东西,应该也是有市场的,关键在于just do it,and keep it on。

惭愧的很,唯一坚持到现在的,只有dota、xy2,噢,还有看小说。其实,我是有能力写个看小说的app的,就是懒!囧…也准备写个dota的app,简介英雄+技能+最优出装备路线

数据都从地图文件读取,就这个把我坑了好几周,音效文件、地图缩略图、角色图标,都有了,还差技能图标,这半拉子工程又搁浅了。。。前阵子,用monkey runner写了个xy2手游python脚本

准备大展宏图,自动挂机、自动打怪、自动任务。。。可是android手机被老婆送人了,哭。。。没经费继续搞下去了。。。只好搞搞网站,坚持写文章,以后打广告!

3、进化的目标
将来成为什么样的人,技术路线、人际关系
这个灵光来自《深渊主宰》、《重卡战车在末世》等小说,逻辑味十足,有借鉴意义。像我这样脑子比较乱的人,很有必要重塑一条主线。

4、过去、现在、将来
勤思,洒脱,突破;十年后看今朝,类比今朝看十年前
怀旧的人哦,骨子里的固执,不想改变,却又不得不变,不如自己先思改变。
神道有斩过去身、现在身、将来身,挺有意思的,还有善恶二尸,本我自由随心。虽然是妄谈,与现实的思辨意义,在自我价值实现后,可以寻找更高的追求,开解迷茫。

5、螺旋式上升
DNA构架,文明的进程,职位的晋升

上面这些关键字,其实是联系在一起的,个人的发展离不开经验沉淀,用钱来养活自己,有个短期的目标,对过去的总结,对未来的展望,以及螺旋式重复的过程,这就是人生。

就写这么多吧,其实还有好多关于成长的话题想谈谈,就想我即将成为父亲的感觉,与刚步入社会的时候相比,差了好多好多。成长,意味着你越来越现实,不管你是否承认,或者

还有那么一点点的幻想,可是行为上,却是越来越与实际接轨,也越来越融入社会。清醒的认识到,你遇到的挫折和失败,大部分来源于你认知现实的偏差。意识到问题,才能解决问题。

与君共勉,早日脱离低级烦恼,实现自我价值。

Xcode – Error ITMS-90168: “The binary you uploaded was invalid.”

今天发布产品,运维人员在用Application Loader提交ipa时,遇到了:

Error ITMS-90168: “The binary you uploaded was invalid.”
The resulting API analysis file is too large. We were unable to validate your API usage prior to delivery. 
This is just an informational message.

网上搜了一下,大部分是指向:
http://stackoverflow.com/questions/32908964/error-itms-90168-the-binary-you-uploaded-was-invalid

然而按照这个操作并没有用,实际上我猜测是打包使用的签名,并不是发布用的签名文件。
也有说必须使用最新版Application Loader就好使的,然而也并没有什么卵用,不过提示不一样了,还是上面的错误码,但是提示签名缺失或者不匹配发布的签名。
于是检查编译脚本,发现是前几天证书过期了,之后使用的是新证书,但是编译脚本里并没有更正过来。。。
更改使用证书文件,果断重新编译,使用最新版本的Application Loader(3.6)提交,通过验证!

另外还有个小问题,我们是发布两个产品,另一个仅仅显示了:

Error ITMS-90168: “The binary you uploaded was invalid.”

检查cert也是匹配的,百思不得其解后,选择重新编译,居然也通过了验证。。。
看来rebuild真的包治百病。。。

最后关于这个问题,我也搜索了很多案例,总结一下经验:
1、使用最新版Xcode自带的Application Loader
2、图标是否缺失
3、签名文件是否匹配
4、rebuild
At last,wish good luck with you.

关于本站建立的初衷

首先谈谈本站域名“qdota.com”,因为本人是资深dota玩家,这样的域名简单也好记😁,以后也许会发一些dota的文章,写个dota app展示一下。
因为建站没经验,只好先用着模版wordpress,基本上就是blog了,可以写写工作中遇到的问题,很多时候搜关键字不好使,这样写的文章应该会被搜录的几率高一点。
然后引入了站点统计,展望一下未来广告收入💰💰💰。。。

任重道远,坚持不懈!争取每天抽事件写点什么,希望几年后,今天的播种会有惊喜。

Android[控件]NumberPicker使用问题汇总

NumberPicker的核心函数:
1、setDisplayedValues

    /**
     * Sets the values to be displayed.
     *
     * @param displayedValues The displayed values.
     *
     * <strong>Note:</strong> The length of the displayed values array
     * must be equal to the range of selectable numbers which is equal to
     * {@link #getMaxValue()} - {@link #getMinValue()} + 1.
     */
    public void setDisplayedValues(String[] displayedValues) {
        if (mDisplayedValues == displayedValues) {
            return;
        }
        mDisplayedValues = displayedValues;
        if (mDisplayedValues != null) {
            // Allow text entry rather than strictly numeric entry.
            mInputText.setRawInputType(InputType.TYPE_CLASS_TEXT
                    | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
        } else {
            mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
        }
        updateInputTextView();
        initializeSelectorWheelIndices();
        tryComputeMaxWidth();
    }

2、setMaxValue

    /**
     * Sets the max value of the picker.
     *
     * @param maxValue The max value inclusive.
     *
     * <strong>Note:</strong> The length of the displayed values array
     * set via {@link #setDisplayedValues(String[])} must be equal to the
     * range of selectable numbers which is equal to
     * {@link #getMaxValue()} - {@link #getMinValue()} + 1.
     */
    public void setMaxValue(int maxValue) {
        if (mMaxValue == maxValue) {
            return;
        }
        if (maxValue < 0) {
            throw new IllegalArgumentException("maxValue must be >= 0");
        }
        mMaxValue = maxValue;
        if (mMaxValue < mValue) {
            mValue = mMaxValue;
        }
        updateWrapSelectorWheel();
        initializeSelectorWheelIndices();
        updateInputTextView();
        tryComputeMaxWidth();
        invalidate();
    }

3、setMinValue

    /**
     * Sets the min value of the picker.
     *
     * @param minValue The min value inclusive.
     *
     * <strong>Note:</strong> The length of the displayed values array
     * set via {@link #setDisplayedValues(String[])} must be equal to the
     * range of selectable numbers which is equal to
     * {@link #getMaxValue()} - {@link #getMinValue()} + 1.
     */
    public void setMinValue(int minValue) {
        if (mMinValue == minValue) {
            return;
        }
        if (minValue < 0) {
            throw new IllegalArgumentException("minValue must be >= 0");
        }
        mMinValue = minValue;
        if (mMinValue > mValue) {
            mValue = mMinValue;
        }
        updateWrapSelectorWheel();
        initializeSelectorWheelIndices();
        updateInputTextView();
        tryComputeMaxWidth();
        invalidate();
    }

4、setValue

    /**
     * Set the current value for the number picker.
     * <p>
     * If the argument is less than the {@link NumberPicker#getMinValue()} and
     * {@link NumberPicker#getWrapSelectorWheel()} is <code>false</code> the
     * current value is set to the {@link NumberPicker#getMinValue()} value.
     * </p>
     * <p>
     * If the argument is less than the {@link NumberPicker#getMinValue()} and
     * {@link NumberPicker#getWrapSelectorWheel()} is <code>true</code> the
     * current value is set to the {@link NumberPicker#getMaxValue()} value.
     * </p>
     * <p>
     * If the argument is less than the {@link NumberPicker#getMaxValue()} and
     * {@link NumberPicker#getWrapSelectorWheel()} is <code>false</code> the
     * current value is set to the {@link NumberPicker#getMaxValue()} value.
     * </p>
     * <p>
     * If the argument is less than the {@link NumberPicker#getMaxValue()} and
     * {@link NumberPicker#getWrapSelectorWheel()} is <code>true</code> the
     * current value is set to the {@link NumberPicker#getMinValue()} value.
     * </p>
     *
     * @param value The current value.
     * @see #setWrapSelectorWheel(boolean)
     * @see #setMinValue(int)
     * @see #setMaxValue(int)
     */
    public void setValue(int value) {
        setValueInternal(value, false);
    }
 
    /**
     * Sets the current value of this NumberPicker.
     *
     * @param current The new value of the NumberPicker.
     * @param notifyChange Whether to notify if the current value changed.
     */
    private void setValueInternal(int current, boolean notifyChange) {
        if (mValue == current) {
            return;
        }
        // Wrap around the values if we go past the start or end
        if (mWrapSelectorWheel) {
            current = getWrappedSelectorIndex(current);
        } else {
            current = Math.max(current, mMinValue);
            current = Math.min(current, mMaxValue);
        }
        int previous = mValue;
        mValue = current;
        updateInputTextView();
        if (notifyChange) {
            notifyChange(previous, current);
        }
        initializeSelectorWheelIndices();
        invalidate();
    }

5、setFormatter

    /**
     * Set the formatter to be used for formatting the current value.
     * <p>
     * Note: If you have provided alternative values for the values this
     * formatter is never invoked.
     * </p>
     *
     * @param formatter The formatter object. If formatter is <code>null</code>,
     *            {@link String#valueOf(int)} will be used.
     *@see #setDisplayedValues(String[])
     */
    public void setFormatter(Formatter formatter) {
        if (formatter == mFormatter) {
            return;
        }
        mFormatter = formatter;
        initializeSelectorWheelIndices();
        updateInputTextView();
    }

仔细观察实现函数,发现它们都会触发一个内部函数updateInputTextView




    /**
     * Updates the view of this NumberPicker. If displayValues were specified in
     * the string corresponding to the index specified by the current value will
     * be returned. Otherwise, the formatter specified in {@link #setFormatter}
     * will be used to format the number.
     *
     * @return Whether the text was updated.
     */
    private boolean updateInputTextView() {
        /*
         * If we don't have displayed values then use the current number else
         * find the correct value in the displayed values for the current
         * number.
         */
        String text = (mDisplayedValues == null) ? formatNumber(mValue)
                : mDisplayedValues[mValue - mMinValue];
        if (!TextUtils.isEmpty(text) && !text.equals(mInputText.getText().toString())) {
            mInputText.setText(text);
            return true;
        }
 
        return false;
    }

这里如果mDisplayedValues不为空时,显示索引为mValue – mMinValue的值!!!
看到这里,大家心里应该有警惕了,如果mDisplayedValues的长度变短了……而索引还未改变……索引就会越界……
那么明显的,改变显示的数据集,长度发生变化的,上面的一系列函数调用顺序就需要好好思量了
a)当displayedValues长度变大时
i、setDisplayedValues
ii、setMaxValue
iii、setMinValue
iV、setValue
b)否则
i、setMaxValue
ii、setMinValue
iii、setDisplayedValues
iV、setValue
a情况,先扩张displayedValues容量,索引仍然保持不变
b情况,先缩小maxValue的值,同时会限制value也缩小,同步的索引也变小,最后赋值displayedValues

文章本应到此为止,可是实际上,在setValue之后,NumberPicker中间的文本并没有显示对应的值,原本以为
添上invalidate就可以了,结果是不行;在界面点击中间的文本后,文字会刷新显示正确。
解决办法如下代码:




    /**
     * NumberPicker EditText
     */
    public static void applyNumberPickerEditTextStyle(NumberPicker picker, String text) {
        EditText editText = null;
        for (int i = 0; i < picker.getChildCount(); i++) {
            View child = picker.getChildAt(i);
            if (child instanceof EditText) {
                editText = (EditText) child;
                break;
            }
        }
        if (editText != null) {
            // disable text input
            editText.setFocusable(false);
            editText.setFilters(new InputFilter[0]);
            editText.setText(text);
        }
    }

AndroidStudio编译异常com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

今天遇到了传说中的“方法数超65536”的问题,贴出Gradle异常如下:

 
FAILURE: Build failed with an exception.
 
* What went wrong:
Execution failed for task ':ToddlerCare:transformClassesWithDexForInnertestJpushNochannelDebug'.
> com.android.build.api.transform.TransformException: 
  com.android.ide.common.process.ProcessException: 
  java.util.concurrent.ExecutionException: 
  com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536
 
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
 
BUILD FAILED
 
Total time: 5 mins 28.887 secs

先贴出官方解决方案的链接:
http://developer.android.com/tools/building/multidex.html

再贴出stackoverflow问题链接:
http://stackoverflow.com/questions/27377080/after-update-of-as-to-1-0-getting-method-id-not-in-0-0xffff-65536-error-i

摘录解决步骤如下:
1、在build.gradle中,设置multiDexEnabled:

android {
   defaultConfig {
      multiDexEnabled true
   }
}

2、引入multidex库

dependencies {
   compile 'com.android.support:multidex:1.0.0'
}

3、将你的Aplication继承自MultiDexApplication,或是在manifest中指定application的属性

android:name="android.support.multidex.MultiDexApplication"

如果你的Application继承自别的类,那就需要重写attachBaseContext

protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
}

Android下载文件异常java.net.ProtocolException: unexpected end of stream

在使用HttpURLConnection下载文件的时候,如果服务器返回的Content-Length字段给出的文件长度比实际文件大小大的时候,客户端在读取流数据到达实际文件大小后,继续读取数据时,就会抛出
java.net.ProtocolException: unexpected end of stream
at com.android.okhttp.internal.http.HttpConnection$FixedLengthSource.read(HttpConnection.java:421)
at com.android.okhttp.okio.RealBufferedSource$1.read(RealBufferedSource.java:349)
at java.io.BufferedInputStream.read(BufferedInputStream.java:290)
at java.io.BufferedInputStream.read(BufferedInputStream.java:290)
……

WordPress设置字体

WordPress主题默认使用的字体“font-family: Merriweather, Georgia, serif;”在显示英文字符的时候,会忽上忽下、忽大忽小,而且阿拉伯数字惨目忍睹,所以急需替换该字体。
自行查找Style.css文件,找到“3.0 – Typography”,在“font-family: “后插入想要设置的字体,例如本站的Menlo,是Mac OS X下Android Studio默认的编辑字体。

附录:

MacOS Windows 10 Ubuntu
Sublime Text Menlo Consolas Monospace
Atom Menlo Consolas DejaVu Sans Mono
IntelliJ Idea Menlo Monospace DejaVu Sans Mono
Eclipse Monaco Consolas Monospace
Visual Studio Consolas
Visual Studio Code Menlo Consolas Droid Sans Mono
XCode Menlo
Notepad++ Courier New
Spacemacs Source Code Pro Source Code Pro Source Code Pro

表格来源:http://blog.jobbole.com/104090/?utm_source=hao.jobbole.com&utm_medium=relatedArticle

参考资源:https://www.anotherhome.net/1010

WordPress文章中插入代码

在上篇文章中讲到了如何设置ICP备案链接的问题,百度搜索到的好多文章都能将代码显示在一块表格区域,于是好奇心大起;使用Chrome浏览器的开发者工具点开详细,发现div标签使用的是wp-syntax,于是搜索到WP-Syntax插件,非常好用,上篇例子中用到的是其xml语言。
使用方法如下:
1、在html文本编辑中插入代码<pre lang=”xml” escaped=”true”>
2、插入你要展示的代码
3、插入结尾符</pre>