Android 常用开源库

正在研究


  • SUtils 封装有许多实用的开发工具类
  • APKParser
  • parceler通过注解的方式序列化对象
    more: Transfuse Transfuse is a Java Dependency Injection (DI) and integration library geared specifically for the Google Android API.

数据持久化


数据处理


Gson

导入

dependencies {
    implementation 'com.google.code.gson:gson:2.8.4'
}

序列化/反序列化

Array<=> json

String namesJson = "['xiaoqiang','chenrenxiang','hahaha']";
Gson gson = new Gson();
String[] nameArray = gson.fromJson(namesJson, String[].class);

json => list

String userJson = "[{'isDeveloper':false,'name':'xiaoqiang','age':26,'email':'578570174@qq.com'},{'isDeveloper':true,'name':'xiaoqiang123','age':27,'email':'578570174@gmail.com'}]";

Gson gson = new Gson();
Type userListType = new TypeToken<ArrayList<User>>(){}.getType();

List<User> userList = gson.fromJson(userJson, userListType); 
控制序列化/反序列化的变量名称

public class User {  
    @Expose()
    String name; // 参与序列化/反序列化

    @Expose(serialize = false, deserialize = false)
    String email; // 不参与序列化,也不参与反序列化

    @Expose(serialize = false)
    int age; // 只参与反序列化

    @Expose(deserialize = false)
    boolean isDeveloper; // 只参与序列化
      @SerializedName(value = "name", alternate = "fullName")
      String userName ;
}

注意:使用以上必须使用如下

GsonBuilder builder = new GsonBuilder();  
builder.excludeFieldsWithoutExposeAnnotation();  
Gson gson = builder.create(); 
字段值为 null 时是否序列化
/**
 * Person 实体一共4个字段:Integer pId、String pName、Date birthday、Boolean isMarry
 * 现在它的属性全部不进行赋值
 */
Person person = new Person();

/** 不对属性值为 null 的字段进行序列化,转换结果会为空*/
String personStr = new Gson().toJson(person);

/** 对属性值为 null 的字段进行序列化*/
String personStrFinal = new GsonBuilder().serializeNulls().create().toJson(person);

System.out.println(personStr);
//输出:{}
System.out.println(personStrFinal);
TypeAdapter

Gson全解析(中)-TypeAdapter的使用

final GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Book.class, new BookTypeAdapter());
final Gson gson = gsonBuilder.create();
/**
 * Integer 转换 防止 后台返回null 转换异常
 */
public class IntegerDefaultAdapter extends TypeAdapter<Integer> {

    @Override
    public void write(JsonWriter jsonWriter, Integer integer) throws IOException {
        jsonWriter.value(String.valueOf(integer));
    }

    @Override
    public Integer read(JsonReader jsonReader) throws IOException {
        try {
            return Integer.valueOf(jsonReader.nextString());
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return -1;
        }
    }
}

/**
 * String 转换 防止 后台返回null 转换异常
 */
public class StringDefaultAdapter extends TypeAdapter<String> {

    @Override
    public void write(JsonWriter jsonWriter, String s) throws IOException {
        jsonWriter.value(s);
    }

    @Override
    public String read(JsonReader jsonReader) throws IOException {
        if (jsonReader.peek() == JsonToken.NULL) {
            jsonReader.nextNull();
            return "";
        } else {
            return jsonReader.nextString();
        }
    }
}

直接操作JSON

【重点】方法根据不同Json类型进行解析

 parse.isJsonArray();
 parse.isJsonNull();
 parse.isJsonObject();
 parse.isJsonPrimitive();

常用操作JsonObject

  String jsonStr = "{\"pId\":9527,\"pName\":\"华安\",\"birthday\":\"Nov 23, 2018 1:50:56 PM\",\"isMarry\":true}";

JsonParser jsonParser = new JsonParser();
/**
* JsonElement parse(String json)
* 如果被解析的字符串不符合 json 格式,则抛出异常
* */
JsonObject jsonObject = jsonParser.parse(jsonStr).getAsJsonObject();

/**
* JsonElement get(String memberName)
* 注意:如果 get 的 key 不存在,则返回 null,如果不加判断而进行取值的话,会抛:java.lang.NullPointerException
* */
Integer pId = jsonObject.get("pId").getAsInt();

JsonArray

String jsonArrayStr = "[{\"pId\":9527,\"pName\":\"华安\",\"isMarry\":true},{\"pId\":8866,\"pName\":\"宁王\",\"isMarry\":false}]";
JsonParser jsonParser = new JsonParser();
JsonArray jsonArray = jsonParser.parse(jsonArrayStr).getAsJsonArray();

构建JSON

JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("pId", 9527);
jsonObject.addProperty("pName", "华安");
jsonObject.addProperty("isMarry", true);
//JsonObject 添加复杂类型属性使用 
//add(String property, JsonElement value)
//JsonObject 与 JsonArray 都是 JsonElement 类的子类

构建工具


MultiChannelPackageTool 快速多渠道打包工具。

开发中实用的工具


UI


主题

显示效果

未读消息

 implementation 'q.rorbin:badgeview:1.1.3'

使用

new QBadgeView(context).bindTarget(textview).setBadgeNumber(5);

https://github.com/qstumn/BadgeView

检测优化工具


  • LeakCanary Android 和 Java 内存泄露检测
    Tutorial ChineseEnglish
    phrof file path: /storage/sdcard0/Download/leakcanary/
    hprof-conv leakCanary
  • apk-method-count 上传Apk,可以根据包名统计方法数量的网站,UI很友好。
  • battery-historian Google 官网方 针对 Api21 5.0以上系统开发的电量使用情况分析工具

功能性开发工具


基础的开发工具


  • JavaVerbalExpressions Java regular expressions made easy. 帮助简单的实现正则表达
  • joda-time-android/ThreeTenABP Java8 的Date包移植到Android中来的库
  • MathView A library for displaying math formula in Android apps.

崩溃错误处理

LoadSir 优雅地处理加载中,重试,无数据等

配置: compile ‘com.kingja.loadsir:loadsir:1.3.6’
ProGuard:

-dontwarn com.kingja.loadsir.**
-keep class com.kingja.loadsir.** {*;}

YCStateLayout 特殊状态提示

状态切换,让 View 状态的切换和 Activity 彻底分离开。

BufferKnife

布局绑定

 static class ViewHolder {
    @BindView(R.id.form_start_date_tv) TextView formStartDateTv;
    ViewHolder(View view) {
      ButterKnife.bind(this, view);
    }
  }

VIEW LISTS

@OnClick({ R.id.door1, R.id.door2, R.id.door3 })

@BindViews({ R.id.first_name, R.id.middle_name, R.id.last_name })
List<EditText> nameViews;

// The apply method allows you to act on all the views in a list at once.

ButterKnife.apply(nameViews, DISABLE);
ButterKnife.apply(nameViews, ENABLED, false);
//Action and Setter interfaces allow specifying simple behavior.
static final ButterKnife.Action<View> DISABLE = new ButterKnife.Action<View>() {
  @Override public void apply(View view, int index) {
    view.setEnabled(false);
  }
};
static final ButterKnife.Setter<View, Boolean> ENABLED = new ButterKnife.Setter<View, Boolean>() {
  @Override public void set(View view, Boolean value, int index) {
    view.setEnabled(value);
  }
};

An Android Property can also be used with the apply method.
ButterKnife.apply(nameViews, View.ALPHA, 0.0f);

RESOURCE BINDING

class ExampleActivity extends Activity {
  @BindString(R.string.title) String title;
  @BindDrawable(R.drawable.graphic) Drawable graphic;
  @BindColor(R.color.red) int red; // int or ColorStateList field
  @BindDimen(R.dimen.spacer) Float spacer; // int (for pixel size) or float (for exact value) field
  // ...
}

automatically be cast.

@OnClick(R.id.submit)
public void sayHi(Button button) {
  button.setText("Hello!");
}

OPTIONAL BINDINGS

@Optional @OnClick(R.id.maybe_missing) void onMaybeMissingClicked() {
  // TODO ...
}

BINDING RESET on Fragments

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fancy_fragment, container, false);
    unbinder = ButterKnife.bind(this, view);
    // TODO Use fields...
    return view;
  }

@Override public void onDestroyView() {
    super.onDestroyView();
    unbinder.unbind();
  }

模块化的开发工具

  • AndroidFilePicker FilePicker 是一个小巧快速的文件选择器框架,以快速集成、高自定义化和可配置化为目标不断前进

网络工具

  • r0capture 安卓应用层抓包通杀脚本

翻遍工具