本来在上一天里,我已经完成了业务的功能。在 Code Review 的时候,代码中有一些不符合 Android 的实践,又或者是有更好的方式。
这些不好的 Code Smell,比如说:
- 在 AndroidManifest.xml 中有没有使用的 Intent Filted
- 测试的时候,漏掉了 null 的情况
- 其它代码中使用了单词缩写,应该改为全称
- 代码中已经有一个 SharedPreferences 工具类
- Toolbar (回退按钮)的图标可以在 Java 代码里设置
花了一个小时重构完之后,我便开始写新的业务卡。
Android Manifest.xml
由于事先不是很了解 Android 的一些 xml 配置,便直接复制了原先的 MainActivity。当然,这些代码是多余的:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
按 Android 官方的文档:
应用的核心组件(例如其 Activity、服务和广播接收器)由 intent 激活。Intent 是一系列用于描述所需操作的信息(Intent 对象),其中包括要执行操作的数据、应执行操作的组件类别以及其他相关说明。Android 系统会查找合适的组件来响应 intent,根据需要启动组件的新实例,并将其传递到 Intent 对象。
组件将通过 intent 过滤器公布它们可响应的 intent 类型。由于Android 系统在启动某组件之前必须了解该组件可以处理的 intent,因此 intent 过滤器在清单中被指定为
元素。一个组件可有任意数量的过滤器,其中每个过滤器描述一种不同的功能。
相关的解释如下
- android.intent.action.MAIN 决定应用程序最先启动的Activity
- android.intent.category.LAUNCHER 决定应用程序是否显示在程序列表里
因此,便删了这两行代码。
重构 DeviceUUID 存储
SharedPreferences API 是一种类似于 LocalStorage 的读写键值接口。最大的区别是,SharedPreferences 是以文件名来保存的。
这就意味着我们需要从某个地方来放置一个文件名相关的变量,因此更好的方式是有一个 SharedPreferences 的公共类。它负责做这些相关的事件:
@SuppressLint("ApplySharedPref")
public void setDeviceUUIDPref(String value) {
pref.edit().putString(PREF_UNIQUE_ID, value).commit();
}
@SuppressLint("ApplySharedPref")
public String getDeviceUUIDPref() {
return pref.getString(PREF_UNIQUE_ID, null);
}
然后,我们从来读取数据:
public class DeviceUtil {
private static String uniqueID = null;
public synchronized static String getDeviceUUID(Context context) {
PreferencesHelper sharedPrefs = new PreferencesHelper(context);
uniqueID = sharedPrefs.getDeviceUUIDPref();
if (uniqueID == null) {
uniqueID = UUID.randomUUID().toString();
sharedPrefs.setDeviceUUIDPref(uniqueID);
}
return uniqueID;
}
}
这样就可以保证,我们读取的是同一个文件。
Android 后退按钮图片
再回到那个 Android 后退按钮的图片问题,可以直接使用:
actionBar.setHomeAsUpIndicator(R.drawable.back_icon);
这样就可以设置上图片了:
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowHomeEnabled(true);
actionBar.setHomeAsUpIndicator(R.drawable.back_icon);
}
Dagger 的 Component 注入多个
因为新建了一个 Activity,就需要注入新的 Component:
@PerActivity
@Component(dependencies = ApplicationComponent.class, modules = HomeModule.class)
public interface HomeComponent {
void inject(HomeFragment homeFragment);
void inject(DetailActivity detailActivity);
}
Android intent 传递 LIST
在实现新业务的过程中,还遇到一个使用 intent 传递 LIST 的情形,一种比较简单的方式是使用 Serializable 来实现:
public class Model implements Serializable {
}
然后 put 进去:
intent.putExtra("model", (Serializable) model);
接着,再用的地方转换一下,读取出来:
List<Model> model = null;
Bundle extras = getIntent().getExtras();
if (extras == null) {
onBackPressed();
} else {
model = (List<Model>) getIntent().getSerializableExtra("model");
}
Android 列表箭头图片
在实现一个列表的时候,用到了一个箭头。这个箭头正好要水平居中,你懂的。就有了如下的 XML:
<android.support.v7.widget.AppCompatImageView
android:id="@+id/chevron_right"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
app:srcCompat="@drawable/ic_chevron_right" />
或许您还需要下面的文章: