在Android中使用HttpClient 4.3.x出现NoSuchFieldError的问题

升级了 HttpClient

前几天看到Apache新发布了 HttpClient 4.3.5,一时手残,将我写的开源项目nForumSDK中的 HttpClient 升级了。

在纯Java的环境下测试了一下,没发现什么问题,新的包还挺好用的,于是就发布了。

过了两天,有人给我发反馈,说在Android应用上测试的时候报错:

java.lang.NoSuchFieldError:org.apache.http.message.BasicLineFormatter.INSTANCE

看了一下,报错在这句话上:

httpClient = HttpClients.createDefault();

根据StackOverFlow,问题在于Android集成了低版本的HttpClient,如果在项目中引用高版本的HttpClient就会导致出错。有三种解决办法:

  1. Apache专门针对这个问题发布了一个 HttpClient for Android 的版本,如果你使用Maven或者Gradle来管理项目,只需要在依赖中加入:

    dependencies{
        compile group: 'org.apache.httpcomponents', name:'httpclient-android', version: '4.3.5'
    }
    
  2. 或下载编译HttpClient for Android 源码, 替换原来的HttpClient即可
  3. 或将原来的HttpClient改包名,从’org.apache.http’到’thank.you.google.http’,以避免冲突
处理 ActionBarDrawerToggle is Deprecated

更新Android Support Library后,自动构建DrawerFragmentLayout,会发现有这样一个Warning:

'Android.support.v4.app.ActionBarDrawerToggle' is deprecated

替换Support Library

查询官方文档可知,我们需要将v4包中的ActionBarDrawerToggle替换为support-library-v7.appcompact.jar中的ActionBarDrawerToggle

替换后,new ActionBarDrawerToggle的时候会发生编译错误:

image1

替换构造函数

根据StackOverFlow中的这个问题,新的Support Library已经不支持传入一个静态的drawer图片作为icon

我们将构造函数:

mDrawerToggle = new ActionBarDrawerToggle(
    getActivity(),
    mDrawerLayout,
    R.drawable.ic_drawer,
    R.string.navigation_drawer_open,
    R.string.navigation_drawer_close
    ) {...}

替换为:

mDrawerToggle = new ActionBarDrawerToggle(
    getActivity(),
    mDrawerLayout,
    R.string.navigation_drawer_open,
    R.string.navigation_drawer_close
    ) {...}

编译、运行,发现新的drawer icon已经变成炫酷的动画形式了!

Git中HEAD和ORIG_HEAD指针指的是什么

一次版本回退后,在历史记录里面看到了这样一张图:

image6

master和dev指针指向的是本地的master分支和dev分支,origin/master和origin/dev指向的是远程仓库的master分支和dev分支,这个很好理解。

HEAD指针代表当前工作路径,HEAD与master指向同一id说明当前处在master分支,这个也不难理解。

关键是ORIG_HEAD指针是个什么东西?翻了翻官方的说明文档,没有发现对这个指针的说明。

搜索了一下,略微明白了一点。

针对某些危险操作,Git通过记录HEAD指针的上次所在的位置ORIG_HEAD提供了回退的功能。当你发现某些操作失误了,比如错误的reset到了一个很早很早的版本,可以使用git reset --hard ORIG_HEAD回退到上一次reset之前。

Git在1.8.5版本之后,加入了HEAD@{}功能,它通过一个链表记录HEAD的移动路径。

输入$ git reflog,结果类似于:

$ git reflog
ea34578 HEAD@{0}: reset: moving to HEAD^
d628164 HEAD@{1}: commit: xxx
ea34578 HEAD@{2}: commit: xxxx
cb926e7 HEAD@{3}: commit: xxxx

每一次移动HEAD指针,Git都会将移动的路径通过链表串起来,链表头部的HEAD@{0}即HEAD指针。

但是HEAD@{1}并不一定是ORIG_HEAD!注意到,ORIG_HEAD仅仅是当进行危险操作(比如merge)时才会变更为HEAD指针的原值,而HEAD@{}链表则记录了每次HEAD的移动(包括commit)。

考虑以下情况:

  • 1.commit -> 2.merge -> 3.commit

此时,HEAD@{0}、HEAD@{1}、HEAD@{2}分别指向3、2、1,而ORIG_HEAD指向的是1而非2。

显然,有了reflog命令后HEAD链表比不知道什么变过的ORIG_HEAD更好用,因此如果你使用的是1.8.5版本之后的Git,推荐使用HEAD{}链表来代替ORIG_HEAD指针。

Github不记录Contributions的问题

Github没有记录我的Contributions

写博客的时候一直用的Sublime Text,然后用配置好的MyGitcommitpush,这次写nForumSDK的时候,用了Eclipse集成的插件EGit,然后发现所有用Eclipsepush的Github都没有记录在Contributions里,Contributions Calendar白白的一片,太伤心了。。

Github为什么不记录

我一直在Dev分支下开发,并未merge到Master分支上,看了一下Github关于Contributions的说明,发现有这样一句话

Commits are only counted if they are made in the default branch (usually master).

只有在默认的Master分支下的Commits才能被算进去,于是我到Master分支下merge了Dev分支,发现仍然没有出现在我的Calendar中……

经过各种排查,发现了问题的所在。我在配置EGit的时候,图方便仅仅将其SSH Key设置为了MyGit的rsa_pub,其他的参数都没有修改,于是在Commit的时候,EGit自动将用户邮箱设为了dss886@我的ip地址.com,这样Github不认为Commit的用户是我……囧。

在Preference->Team->Git->Configuration中添加两条记录:user.name=dss886user.email=dss886@gmail.com,再进行Commit,发现已经记录在Contributions Calendar中了!

什么样的Contribution Github才记录?

翻译一下Gihub关于Contributions的说明,希望能帮到大家,不要让辛辛苦苦写的代码被Github忽视了:)

会被记录的Contribution情形

1. Issues and pull requests

同时满足以下两个条件将会被计入Contribution

  • 这个操作是在一年之内。(Calendar只显示一年之内的Contribution)
  • 这个操作是针对一个独立的仓库。(在Fork的仓库中进行的操作不会被记录)

2. Commits

同时满足以下四个条件将会被计入Contribution

  • Commits是在一年之内。(Calendar只显示一年之内的Contribution)
  • 进行Commits的用户被关联到了你的Github帐号中(使用SSH方式能够不输入帐号密码进行push,如果此时你Commit的帐号不在Github帐号列表中,就不会被计入Contribution)
  • 是在一个独立的版本库中进行Commit。(在Fork的仓库中进行Commit则不会被记录)
  • 是在这个版本库的默认分支(通常是Master)进行的Commit。(如果你在Dev分支下进行开发,你的Commit不会被计入Contribution,但是并不会丢失它们,一旦当你Merge到Master分支后,所有的Commit都会被重新计入。多人协作也是同理,只有被并入Master分支的Commit才会被计入,如果你的Commit在合并时被组长丢弃,在Github看来,你就白干了……)

3. 附加条件

如果你Commit的仓库不是你创建的,那么至少要满足以下四条之一,才会被计入Contribution

  • 你是这个仓库的协作者,或者是这个版本库的拥有组织中的一员。
  • 你fork过这个仓库。
  • 你对这个仓库发起过pull request或者issue。
  • 你对这个仓库标记了Star。

(私有仓库的Commit也会被计入Contribution,没有这个私有仓库权限的用户将看不到这个Commit的跳转链接)

Contributions未被Github计入的几个常见原因

  • 进行Commits的用户没有被关联到你的Github帐号中。
  • 不是在这个版本库的默认分支进行的Commit。
  • 这个仓库是一个Fork仓库,而不是独立仓库。
Win7/Win8下双击运行jar程序的方法

问题

老妈喜欢看小说,又不会下载,于是用Java写了个自动下载小说的小程序

我用的Swing UI,直接生成了.jar文件,双击即可运行

很诡异的是,用Eclipse直接run可以运行,但是Export出jar文件以后双击却没有反应

探究

怀疑是不是Eclipse的导出功能坏掉了,于是用了flatjar等工具重新打包,仍然不行

走了很多弯路以后终于Google到了问题的所在:

win7/win8的jar文件默认关联的程序是java.exe而不是javaw.exe

右键 -> 打开方式里面这两个程序也分辨不出来,都显示的是:

Java(TM) Platform SE binary

解决

右击jar包,在打开方式 -> 选择默认程序里面选中jdk目录下bin文件夹中的javaw.exe

编辑注册表,在下列项中:

HKEY_CLASSES_ROOT\Applications\javaw.exe\shell\open\command

修改值为:

"X:\jdk1.7\bin\javaw.exe" -jar "%1"

(即只需要在原来的%1前面添加-jar)

问题解决!