4.5使用Android库
问题
您要向应用程序添加库模块。
解
使用库插件并将库模块添加为依赖关系。
讨论
您可以使用Java库(以jar文件的形式)为应用程序添加大量附加功能。 Recipe 1.5详细讨论了这一点,展示了如何使用依赖块。例如,要使用Google的Gson库来解析JSON数据,请将依赖关系添加到模块构建文件中,如示例4-19所示。
实施例4-19。添加Google的Gson库
dependencies {
compile 'com.google.code.gson:gson:2.6.2'
}
Android库超越了Java库,因为它们包括来自Android API的类,任何所需的资源,或者两者。当项目构建时,Gradle将Android库汇编成aar(Android Archive)文件,它们类似于jar文件,但包括Android依赖项。
从Gradle的角度来看,Android库是来自根目录的子项目。这意味着他们像Android应用程序,但在一个子目录。因此,添加的模块的名称(Android Studio称为模块)被添加到settings.gradle文件中,如例4-20所示。
实例4-20。包含添加的模块的settings.gradle文件
include ':app', ':icndb'
在这种情况下,Android库模块称为icndb,它代表Internet Chuck Norris数据库,它以JSON响应的形式提供Chuck Norris笑话。网站上的API页面如图4-2所示。
图4-2。 ICNDB网站的API页面
作为Android库的一个示例,此网站将作为RESTful Web服务访问,返回的JSON数据将被解析,并将生成的笑话添加到TextView中的Welcome活动。
要在Android Studio中创建库模块,请使用“新建模块”向导并选择“Android库”类型,如图4-3所示。
新建模块向导的其他选项包括Java库和导入.JAR / .AAR软件包等等。
图4-3。新建模块向导中的Android库选项
给库一个名字后,你可以添加任何类型的活动,如果有的话。完成向导将创建库目录,并将其添加到根项目中的settings.gradle文件中。
每个库都有自己的Gradle构建文件,它支持与根项目相同的设置。您可以指定最低和目标SDK版本,自定义构建类型,添加风格,并根据需要修改依赖关系。重要的区别是Gradle构建使用了不同的插件,如例4-21所示。
实例4-21。 ICNDB库模块的build.gradle文件
apply plugin: 'com.android.library' //1
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
packagingOptions {//2
exclude 'META-INF/notice.txt'
exclude 'META-INF/license.txt'
exclude 'LICENSE.txt'
}
defaultConfig {
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
}
dependencies {
compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.retrofit2:retrofit:2.0.1'
compile 'com.squareup.retrofit2:converter-gson:2.0.1'
}
1使用库插件
2从多个依赖项中排除冲突的文件
构建文件添加了Retrofit 2项目作为依赖项,以及用于JSON消息的Gson转换器,以及前面讨论的Gson库。
注意也使用了packagingOptions块。这允许您排除显示在多个依赖项中的相同名称的文件。
如果使用这些库,ICNDB库的实现变得很简单,如例4-22所示。
实例4-22。 JokeFinder类,它完成所有的工作
public class JokeFinder {
private TextView jokeView;
private Retrofit retrofit;
private AsyncTask<String, Void, String> task;
public interface ICNDB {//1
@GET("/jokes/random")
Call<IcndbJoke> getJoke(@Query("firstName") String firstName,
@Query("lastName") String lastName,
@Query("limitTo") String limitTo);
}
public JokeFinder() {
retrofit = new Retrofit.Builder()//2
.baseUrl("http://api.icndb.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
public void getJoke(TextView textView, String first, String last) {
this.textView = textView;
new JokeTask().execute(first, last);
}
private class JokeTask extends AsyncTask<String, Void, String> {//3
@Override
protected String doInBackground(String... params) {
ICNDB icndb = retrofit.create(ICNDB.class);
Call<IcndbJoke> icndbJoke = icndb.getJoke(
params[0], params[1], "[nerdy]");
String joke = "";
try {
joke = icndbJoke.execute().body().getJoke();
} catch (IOException e) {
e.printStackTrace();
}
return joke;
}
@Override
protected void onPostExecute(String result) {
jokeView.setText(result);
}
}
}
1用于改进GET请求访问的接口
2使用Gson转换器构建Retrofit实例
3异步任务访问Web服务的UI线程
JokeFinder类使用提供的英雄的名字和姓氏访问ICNDB Web服务,使用异步任务,以便在UI线程之外执行操作。 getJoke方法包括一个TextView的参数,一旦对结果的解析完成,JokeTask更新。
IcndbJoke任务是一个简单的POJO,映射JSON响应。响应的形式如图4-4所示。
JSON响应相当小,因此相应的IcndbJoke类也很简单,如例4-23所示。
实例4-23。 IcndbJoke类POJO,它映射到JSON格式
public class IcndbJoke {
private String type;
private Joke value;
public String getJoke() {
return value.getJoke();
}
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public Joke getValue() { return value; }
public void setValue(Joke value) { this.value = value;}
private static class Joke {
private int ID;
private String joke;
private String[] categories;
public int getId() { return ID; }
public void setId(int ID) { this.id = ID; }
public String getJoke() { return joke; }
public void setJoke(String joke) { this.joke = joke; }
public String[] getCategories() { return categories; }
public void setCategories(String[] categories) {
this.categories = categories;
}
}
}
图4-4。来自ICNDB服务的JSON响应
这是库。应用程序通过其JokeFinder类使用库。这在模块构建文件中使用项目依赖关系可用,如示例4-24所示。
实施例4-24。在应用程序中使用ICNDB模块
apply plug-in: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
// ... all the regular settings ...
}
dependencies {
compile project(':icndb')//1
}
1在编译时使用icndb库
编译依赖项使用project方法,它将包含模块的子目录作为参数。结果是Gradle知道在构建应用程序之前构建ICNDB模块,并且在编译时使其类可用。
WelcomeActivity调用JokeFinder中的getJoke方法,提供对要更新的TextView的引用,以及从SharedPreferences对象提供的名和姓,如例4-25所示,其中所有其他部分都已省略。
实例4-25。从WelcomeActivity调用getJoke方法
public class WelcomeActivity extends Activity {
private TextView jokeText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
jokeText = (TextView) findViewById(R.id.joke_text);
final SharedPreferences prefs =
PreferenceManager.getDefaultSharedPreferences(this);
new JokeFinder().getJoke(jokeText,
prefs.getString("first", "Xavier"),
prefs.getString("last", "Ducrohet"));
}
}
Xavier Ducrohet是Android项目Gradle插件的负责人,也是Google Studio Android Studio开发团队的负责人。
样本运行如图4-5所示。
图4-5。运行应用程序
构建过程本身在icndb / build / outputs / arr目录中生成库的调试和发行版本,如例4-26所示。
实施例4-26。输出Android库归档文件
> ./gradlew build
> ls icndb / build / outputs / aar
icndb-debug.aar icndb-release.aar
aar文件可以发布到存储库供以后由其他应用程序使用。
总结:
•Android库项目是需要Android依赖项的Java项目,例如来自Android API或资源或两者的类
•Gradle使用多个项目构建的子目录,其中每个子项目都添加到顶级settings.gradle文件
•在Android Studio中,使用“新建模块”向导中的“Android库”选项创建Android库项目
•库项目使用com.android.library插件
•应用程序构建文件使用项目(“:library”)依赖关系从应用程序访问库类
遵循此模式,您可以向Android库添加功能,并在其他应用程序中重用它们。