Born again shelter - android
type: channel
link: https://bash.kmxz.net/tag/android/
items: 使用 Interface 的品味
items: Why you should never use android:onClick XML attribute
items: 再见 Evernote

使用 Interface 的品味
type: item
date: 2016-05-24T11:47:00+00:00
description: Android 开发中，用得最常见的 interface 之一便是 OnClickListener 了。不使用 android:onClick 属性的话，自然就不得不去 implement OnClickListener。假设我们不使用任何框架或是架构模式，只是写一个简单的 Activity；在一个 Activity 中有多个可点击的按钮时，我的同事会这么写：public class ExampleActivity extends Activity implements OnClickListener { @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_example); findViewById(R.id.first_button).setOnClickListener(this); findViewById(R.id.second_button).setOnClickListener(this); } @Override public void onClick(final View v) { switch (v.getId()) { case R.id.first_button: // bla bla bla break; case R.id.second_button: // bra bra bra } } } 事实上，Android 官方有些 sample 里面也是这么写的。然而在我看来，这么写代码是非常不优雅的，因为一个 OnClickListener 的实现，只应该关注和点击事件本身相关的内容，它的含义和 Activity 的含义是截然无关的，让同一个类继承/实现他们，会使得这个类的含义变得不清晰。同时，这样还给 ExampleActivity 类增加了一个 public 的方法，削弱了这个类的封闭性。所以如果像下面这样，会好不少：public class ExampleActivity extends Activity { private OnClickListener onClickListener = new OnClickListener() { @Override public void onClick(final View v) { switch (v.getId()) { case R.id.first_button: // bla bla bla break; case R.id.second_button: // bra bra bra } } }; @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_example); findViewById(R.id.first_button).setOnClickListener(onClickListener); findViewById(R.id.second_button).setOnClickListener(onClickListener); } } 这样写体现了 composition over inheritance 的思想。它避免了上面的所有问题，看起来舒服得多。不过，这样还是让阅读代码时很不方便——看到 onCreate 里面时，还不得不经常滚动到声明 onClickListener 的地方去，并且在 onClick 中艰难地寻找真正和某个特定按钮相关的代码。当然这两个问题之前那个版本也都无法避免。另一件糟糕的事情是，不同按钮的 listener 逻辑很可能是相对独立的，放到同一个 onClickListener 里，还是很丑陋。所以为了进一步避免这几个问题，我一向都是用下面这样的写法：public class ExampleActivity extends Activity { @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_example); findViewById(R.id.first_button).setOnClickListener(new OnClickListener()…

Why you should never use android:onClick XML attribute
type: item
date: 2016-05-19T07:52:00+00:00
description: Recently, I made a decision to disallow programmers to use android:onClick XML attributes to add click event listeners. Existing usages will be removed too. Actually, the attribute itself was a very bad design, considering that web frontend developers has switched from onclick HTML attribute to addEventListener API for a long time. Here are the real reasons why android:onClick XML attribute should be avoided:If an ancestor element has theme applied, android:onClick no longer works, because the program will look for the click handler from ContextThemeWrapper instead of Activity (see http://stackoverflow.com/questions/29525644/). When applying a theme, programmers may not realize the problem.Android look for the specified method from the parent Activity. When programmers change an Activity into a Fragment, they may be ignoring this problem.To make the two problems above more severe, onClick uses reflection. It therefore prevents the compiler from telling you problems. You app will crash at run time.As it uses reflection, performance will be compromised.Android provides android:onClick attribute, but no android:onChange or any other XML attributes for event listeners. Considering click listeners aren't really different from other event listeners, keeping them consistent will be good.When using android:onClick, one must create a public method with parameter (View view). Android Lint will then complain "unused parameter".Adding a public method is not elegant in any way.

再见 Evernote
type: item
date: 2014-11-11T18:14:00+00:00
description: 用 Evernote 有三四年了。最早是因为 Google Notebook 关停才不得已转到 Evernote 的。Evernote 免费版有一些限制，比如同步流量限制、Android 客户端不能离线、Android 客户端不能设置密码；要 Premium 才能使用；而 Premium 又太贵，于是去年我也用了一阵子的有道云笔记，但是后来由于用户体验、隐私等等原因，用了一个月也就没再用了，还是坚守 Evernote。但是 Evernote 有几大问题，是即使购买 Premium 也无法解决的：一是没有 Linux 客户端，二是出现 conflict 时很傻逼，三是组织层级还是不够。同时解决这三个问题的方法倒也简单：直接全部笔记用 Markdown 一类的文本写，然后 GitHub 上面弄个 private repo 来放。缺点在于放短小的笔记即时同步不那么方便，但是那种情况下我用 Google Keep 就好了。打算正式抛弃 Evernote。﻿