Android Development: Some useful libraries (part I)
你好! 从我自己的经验。 我想出了这个可能最常使用并获得社群批准的库名单(也是谷歌的官方名单)。 您可能不需要为每个应用程序包括所有这些库,但这里的想法是要选择正确的。
支持库
从Google向旧版本的Android提供新的API和稳定性修复程序。 有几个版本,有特定的最低SDK版本,其中一些可以帮助你找到问题,并改进你的代码,如android注释支持:
compile 'com.android.support:support-v4:x.y.z'
compile 'com.android.support:appcompat-v7:x.y.z'
compile 'com.android.support:support-v13:x.y.z'
compile 'com.android.support:design:x.y.z'
compile 'com.android.support:support-annotations:x.y.z'
...
Multidex支持库
如果你曾经遇到超过65k方法错误,而你建立你的应用程序,这可能是你的解决(但这应该是最后的手段,你应该尝试剥离你的应用程序第一):
提供Google提供的各种服务和API,从Google地图到Android Pay,从穿戴式设备到广告。 它是从Google Play商店更新的,因此它的Android操作系统版本是独立的。 要包含在您的项目中:
compile 'com.google.android.gms:play-services:x.y.z'
如果你不想包括整个包(因为它是非常大,你可能会遇到超过65k的方法错误),你可以选择性地包括你想要使用的模块:
compile 'com.google.android.gms:play-services-wearable:x.y.z'
compile 'com.google.android.gms:play-services-maps:x.y.z'
当涉及到实现REST API时,Retrofit仍然是我最喜欢的库。 从他们的网站:“Retrofit将您的REST API变成Java接口。”这是一个优雅的解决方案,用于在项目中组织API调用。 请求方法和相对URL添加了注释,这使代码干净和简单。 使用注释,您可以轻松添加请求正文,操作网址或标题并添加查询参数。 要包括此库,请将其添加到您的build.gradle文件中:
compile 'com.squareup.retrofit2:retrofit:2.y.z'
compile 'com.squareup.retrofit2:converter-gson:2.y.z'
public interface RestAPI{
@GET(BuildConfig.PATH_TO_MOVIES_SERVICE)
Observable<List<Movie>> loadMovies();
// Helper class that sets up new service
class Factory {
public static RestAPI create() {
Retrofit retrofit =
new Retrofit.Builder()
.baseUrl(BuildConfig.API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
return retrofit.create(RestAPI.class);
}
}
compile 'io.reactivex:rxjava:x.y.z'
compile 'io.reactivex:rxandroid:x.y.z'
compile 'io.reactivex:rxjava:x.y.z'
Let’s take an example:
private class SomeWebServiceTask extends
AsyncTask <String,Result,Void>
{
protected Result doInBackground(String... someData) {
Result result = webService.doSomething(someData);
return result;
}
protected void onPostExecute(Result result) {
if (result.isSuccess() {
resultText.setText("Hello, world!");
}
}
}
或者
webService.doSomething(someData)
.observeOn(AndroidSchedulers.mainThread())
.subscribe( result -> resultText.setText("Hello, world!"),
e -> handleError(e));
在每个Android应用程序中,您必须对布局中的每个视图使用findViewById()方法,以便在应用程序的代码中使用。 但是随着应用程序设计的复杂布局,对这个方法的调用变得重复,这就是ButterKnife库所在。
这是所有你需要包括这个库:
private TextView mFirstNameLabel;
private TextView mLastNameLabel;
private Button mSubmitButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFirstNameLabel = (TextView) findViewById(R.id.firstnameLabel);
mLastNameLabel = (TextView) findViewById(R.id.lastnameLabel);
mSubmitButton = (Button) findViewById(R.id.submitButton);
mSubmitButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO call ...
}
});
}
或者
@Bind(R.id.firstnameLabel) TextView mFirstNameLabel;
@Bind(R.id.lastnameLabel) TextView mLastNameLabel;
@OnClick(R.id.submitButton) void submit() {
// TODO call ...
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
ButterKnife.bind(this);
}
第二个代码块使用库,它使用注释通过为您创建样板代码来“绑定”视图。 ButterKnife是小巧,简单,轻量级的,因为它使你的生活作为一个开发人员更容易,你应该几乎总是使用它。 这将是巨大的,如果Android SDK本身可以以这种方式改进!
Picasso/Glide. 优秀和高效的图像加载库从网络和更多。 但是,在我看来,Glide是现在的最佳选择。 它包含在Google I / O 2014官方应用程序中。 这是所有你需要包括这个库:
/** Picasso **/
compile 'com.squareup.picasso:picasso:x.y.z'
/** Glide **/
compile 'com.github.bumptech.glide:glide:x.y.z'
@Bind(R.id.image_view) ImageView imageView;
Picasso.with(this).load(imageUrl).into(imageView);
Glide.with(this).load(imageUrl).into(imageView);
compile 'com.jakewharton.timber:timber:x.y.z'
典型的日志如下所示:
public static String TAG = "ClassName";
...
Log.e(TAG, “A message here”);
但是使用Timber,您可以在应用程序创建中使用类似以下代码:
@Override
public void onCreate() {
super.onCreate();
if (BuildConfig.DEBUG) {
Timber.plant(new DebugTree());
} else {
Timber.plant(new CrashReportingTree());
}
}
/** 一个记录崩溃报告重要信息的树。
private static class CrashReportingTree extends Timber.HollowTree {
@Override
public void i(String message, Object... args) {
// TODO e.g., Crashlytics.log(String.format(message, args));
}
@Override
public void i(Throwable t, String message, Object... args) {
i(message, args); // Just add to the log.
}
@Override
public void e(String message, Object... args) {
i("ERROR: " + message, args); //Just add to the log.
}
@Override
public void e(Throwable t, String message, Object... args) {
e(message, args);
// TODO e.g., Crashlytics.logException(t);
}
}
//
是一个简化应用程序的不同部分之间的通信的库。 例如,将某个活动从某个活动发送到正在运行的服务,或者在片段之间轻松交互。 要包括它添加到您的gradle:
compile 'com.squareup:otto:x.y.z'
以下是我们使用的示例,如果Internet连接丢失,显示如何通知活动:
public class NetworkStateReceiver extends BroadcastReceiver {
// 如果没有互联网连接,则发生事件
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if(intent.getExtras()!=null) {
NetworkInfo ni=(NetworkInfo) intent.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);
if(ni!=null && ni.getState()==NetworkInfo.State.CONNECTED)
{
// there is Internet connection
}
else if(intent.getBooleanExtra
(ConnectivityManager.EXTRA_NO_CONNECTIVITY, Boolean.FALSE))
{
// no Internet connection,send network state changed
Bus.post(newNetworkStateChanged(false));
}
}
// 事件
public class NetworkStateChanged {
private mIsInternetConnected;
public NetworkStateChanged(boolean isInternetConnected) {
this.mIsInternetConnected = isInternetConnected;
}
public boolean isInternetConnected() {
return this.mIsInternetConnected;
}
}
public class MainActivity extends Activity {
public static Bus bus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bus = new Bus();
bus.register(this); // register Otto event Bus
}
@Override
protected void onDestroy() {
super.onDestroy();
bus.unregister(this); // unregister Otto event Bus
}
//Method that will be called when someone posts an event NetworkStateChanged
public void onEventMainThread(NetworkStateChanged event) {
if (!event.isInternetConnected()) {
Toast.makeText(this, "No Internet connection!", Toast.LENGTH_SHORT).show();
}
}
}
private final Subject<Object, Object> bus = new SerializedSubject<>(PublishSubject.create());
public void post(Object o) {
bus.onNext(o);
}
// Subscribe to this Observable. to get it
public Observable<Object> getEvents() {
return bus;
}
}
// Subscribe to the event
getEvents().subscribe(new Action1<Object>() {
@Override
public void call(Object o) {
if(o instanceof AnswerEvent){
// TODO
}
}
这是一种使用Java 8 Lambdas到Java 6/7(以及Android)的方法。 使你的代码更清洁,结合它与RxJava和你是坚实的。 这是所有你需要包括它:
classpath 'me.tatarka:gradle-retrolambda:x.y.z'
apply plugin: 'me.tatarka.retrolambda'
下面是一个简单的例子如何使用Retrolambda & RxJava
Observable.just("Hello, world!")
.subscribe(s -> System.out.println(s));
Dagger 2是著名的Dagger依赖注入库的继承者,我强烈推荐它。 其中一个主要的改进是在生成的注入代码中使用零反射,这使得调试更容易。
Dagger创建你的类的实例,并满足他们的依赖。 它依赖于javax.inject.Inject注释来标识哪些构造函数或字段应被视为依赖关系。 让我们来看看这个着名的CoffeeMaker示例:class Thermosiphon implements Pump {
private final Heater heater;
@Inject
Thermosiphon(Heater heater) {
this.heater = heater;
}
...
}
An example with direct injection into fields:
class CoffeeMaker {
@Inject Heater heater;
@Inject Pump pump;
...
}
Dependencies are provided via modules and @Provides annotation from Dagger:
@Module
class DripCoffeeModule {
@Provides
Heater provideHeater() {
return new ElectricHeater();
}
@Provides
Pump providePump(Thermosiphon pump) {
return pump;
}
}
要使用它添加到build.gradle文件:
compile 'com.google.dagger:dagger:x.y.z'
是Android中的另一种类型的数据库。 但是,非常重要的是,Realm不使用SQLite。 如果使用ORMLite或ActiveAndroid或任何其他类似的库,您的数据存储在SQLite数据库中,因为这些库给我们在SQLite上只有一个覆盖。 与Realm它是完全不同的是没有SQLite。 这就是你需要使用它:classpath 'io.realm:realm-gradle-plugin:x.y.z'
//
apply plugin: 'realm-android'
这里有一个非常简单的例子如何使用它:
public class Book extends RealmObject {
@Required
private String title;
public String getTitle() {
return title;
}
public void setTitle(final String title) {
this.title = title;
}
}
// MAIN_ACTIVITY
public class MainActivity extends Activity {
private Realm mRealm;
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mRealm = Realm.getInstance(getContext());
}
@Override
public void onDestroy() {
super.onDestroy();
mRealm.close();
}
// Example of add/ remove a book
@OnClick(R.id.add)
public void onAddClick() {
mRealm.beginTransaction();
Book book = mRealm.createObject(Book.class);
book.setTitle(getTrimTitle());
mRealm.commitTransaction();
}
@OnClick(R.id.remove)
public void onRemoveClick() {
mRealm.beginTransaction();
RealmResults<MyBook> books = mRealm.where(Book.class)
.equalTo("title",getTrimTitle())
.findAll();
if(!books.isEmpty()) {
for(int i = books.size() - 1; i >= 0; i--) {
books.get(i).removeFromRealm();
}
}
mRealm.commitTransaction();
}
private String getTrimTitle() {
return mEditTitle.getText().toString().trim();
}
ViewPropertyAnimator在API级别12引入,允许您使用单个Animator实例简单高效地对多个视图属性执行动画操作(并行)。 对我们来说实现程序化是简单和整洁的:
// Animate Button
mButton.animate()
.alpha(1f)
.scaleX(1f)
.scaleY(1f)
.translationZ(10f)
.setInterpolator(new FastOutSlowInInterpolator())
.setStartDelay(200)
.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) { }
@Override
public void onAnimationEnd(Animator animation) { }
@Override
public void onAnimationCancel(Animator animation) { }
@Override
public void onAnimationRepeat(Animator animation) { }
})
.start();
转换框架
Android转换框架允许您配置应用程序用户界面中的更改的外观。 它提供工具,以有效地管理和导航生活的过渡。 这个框架有一些限制:
应用于SurfaceView的动画可能无法正确显示。 SurfaceView实例从非UI线程更新,因此更新可能与其他视图的动画不同步。
一些特定的过渡类型在应用于TextureView时可能不会产生所需的动画效果。
扩展AdapterView的类(如ListView)以与转换框架不兼容的方式管理其子视图。 如果尝试对基于AdapterView的视图进行动画处理,则设备显示可能会挂起。
如果您尝试使用动画调整TextView的大小,则在对象完全调整大小之前,文本将会弹出到新位置。 要避免此问题,请不要对包含文本的视图的大小调整进行动画处理。
你好! 从我自己的经验。 我想出了这个可能最常使用并获得社群批准的库名单(也是谷歌的官方名单)。 您可能不需要为每个应用程序包括所有这些库,但这里的想法是要选择正确的。
支持库
从Google向旧版本的Android提供新的API和稳定性修复程序。 有几个版本,有特定的最低SDK版本,其中一些可以帮助你找到问题,并改进你的代码,如android注释支持:
compile 'com.android.support:support-v4:x.y.z'
compile 'com.android.support:appcompat-v7:x.y.z'
compile 'com.android.support:support-v13:x.y.z'
compile 'com.android.support:design:x.y.z'
compile 'com.android.support:support-annotations:x.y.z'
...
Multidex支持库
如果你曾经遇到超过65k方法错误,而你建立你的应用程序,这可能是你的解决(但这应该是最后的手段,你应该尝试剥离你的应用程序第一):
compile 'com.android.support:multidex:x.y.z'
提供Google提供的各种服务和API,从Google地图到Android Pay,从穿戴式设备到广告。 它是从Google Play商店更新的,因此它的Android操作系统版本是独立的。 要包含在您的项目中:
compile 'com.google.android.gms:play-services:x.y.z'
如果你不想包括整个包(因为它是非常大,你可能会遇到超过65k的方法错误),你可以选择性地包括你想要使用的模块:
compile 'com.google.android.gms:play-services-wearable:x.y.z'
compile 'com.google.android.gms:play-services-maps:x.y.z'
...
当涉及到实现REST API时,Retrofit仍然是我最喜欢的库。 从他们的网站:“Retrofit将您的REST API变成Java接口。”这是一个优雅的解决方案,用于在项目中组织API调用。 请求方法和相对URL添加了注释,这使代码干净和简单。 使用注释,您可以轻松添加请求正文,操作网址或标题并添加查询参数。 要包括此库,请将其添加到您的build.gradle文件中:
compile 'com.squareup.retrofit2:retrofit:2.y.z'
compile 'com.squareup.retrofit2:converter-gson:2.y.z'
compile 'com.squareup.retrofit2:adapter-rxjava:2.y.z'
public interface RestAPI{
@GET(BuildConfig.PATH_TO_MOVIES_SERVICE)
Observable<List<Movie>> loadMovies();
// Helper class that sets up new service
class Factory {
public static RestAPI create() {
Retrofit retrofit =
new Retrofit.Builder()
.baseUrl(BuildConfig.API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
return retrofit.create(RestAPI.class);
}
}
RxJava
是Reactive Extensions的Java VM实现,帮助您组合异步,基于事件,类似于代码的流和添加功能编程范例。 这是所有你需要包括这个库:compile 'io.reactivex:rxjava:x.y.z'
RxAndroid
包装RxJava库。 它增加了Android特定线程的功能。 注意RxAndroid自动包括一个版本的RxJava。 但是,因为RxAndroid版本是在它后面,如果你想使用最新的RxJava,那么包括两个像:compile 'io.reactivex:rxandroid:x.y.z'
compile 'io.reactivex:rxjava:x.y.z'
Let’s take an example:
private class SomeWebServiceTask extends
AsyncTask <String,Result,Void>
{
protected Result doInBackground(String... someData) {
Result result = webService.doSomething(someData);
return result;
}
protected void onPostExecute(Result result) {
if (result.isSuccess() {
resultText.setText("Hello, world!");
}
}
}
或者
webService.doSomething(someData)
.observeOn(AndroidSchedulers.mainThread())
.subscribe( result -> resultText.setText("Hello, world!"),
e -> handleError(e));
是啊! 说再见AsyncTasks。
在每个Android应用程序中,您必须对布局中的每个视图使用findViewById()方法,以便在应用程序的代码中使用。 但是随着应用程序设计的复杂布局,对这个方法的调用变得重复,这就是ButterKnife库所在。
这是所有你需要包括这个库:
compile 'com.jakewharton:butterknife:x.y.z'
private TextView mFirstNameLabel;
private TextView mLastNameLabel;
private Button mSubmitButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFirstNameLabel = (TextView) findViewById(R.id.firstnameLabel);
mLastNameLabel = (TextView) findViewById(R.id.lastnameLabel);
mSubmitButton = (Button) findViewById(R.id.submitButton);
mSubmitButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO call ...
}
});
}
或者
@Bind(R.id.firstnameLabel) TextView mFirstNameLabel;
@Bind(R.id.lastnameLabel) TextView mLastNameLabel;
@OnClick(R.id.submitButton) void submit() {
// TODO call ...
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
ButterKnife.bind(this);
}
第二个代码块使用库,它使用注释通过为您创建样板代码来“绑定”视图。 ButterKnife是小巧,简单,轻量级的,因为它使你的生活作为一个开发人员更容易,你应该几乎总是使用它。 这将是巨大的,如果Android SDK本身可以以这种方式改进!
Picasso/Glide. 优秀和高效的图像加载库从网络和更多。 但是,在我看来,Glide是现在的最佳选择。 它包含在Google I / O 2014官方应用程序中。 这是所有你需要包括这个库:
/** Picasso **/
compile 'com.squareup.picasso:picasso:x.y.z'
/** Glide **/
compile 'com.github.bumptech.glide:glide:x.y.z'
这篇文章解释了Picasso Glide之间的区别。
@Bind(R.id.image_view) ImageView imageView;
Picasso.with(this).load(imageUrl).into(imageView);
这里有一个简单的例子,您可以使用Glide 将图像从URL加载到ImageView中:
Glide.with(this).load(imageUrl).into(imageView);
Timber
是一个轻量级库,可以在不同地方写入日志,并以集中的方式控制它的工作方式。 很容易将其添加为Android Studio项目的依赖项;compile 'com.jakewharton.timber:timber:x.y.z'
典型的日志如下所示:
public static String TAG = "ClassName";
...
Log.e(TAG, “A message here”);
但是使用Timber,您可以在应用程序创建中使用类似以下代码:
@Override
public void onCreate() {
super.onCreate();
if (BuildConfig.DEBUG) {
Timber.plant(new DebugTree());
} else {
Timber.plant(new CrashReportingTree());
}
}
/** 一个记录崩溃报告重要信息的树。
private static class CrashReportingTree extends Timber.HollowTree {
@Override
public void i(String message, Object... args) {
// TODO e.g., Crashlytics.log(String.format(message, args));
}
@Override
public void i(Throwable t, String message, Object... args) {
i(message, args); // Just add to the log.
}
@Override
public void e(String message, Object... args) {
i("ERROR: " + message, args); //Just add to the log.
}
@Override
public void e(Throwable t, String message, Object... args) {
e(message, args);
// TODO e.g., Crashlytics.logException(t);
}
}
//
Timber.i("Message here");
是一个简化应用程序的不同部分之间的通信的库。 例如,将某个活动从某个活动发送到正在运行的服务,或者在片段之间轻松交互。 要包括它添加到您的gradle:
compile 'com.squareup:otto:x.y.z'
以下是我们使用的示例,如果Internet连接丢失,显示如何通知活动:
public class NetworkStateReceiver extends BroadcastReceiver {
// 如果没有互联网连接,则发生事件
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if(intent.getExtras()!=null) {
NetworkInfo ni=(NetworkInfo) intent.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);
if(ni!=null && ni.getState()==NetworkInfo.State.CONNECTED)
{
// there is Internet connection
}
else if(intent.getBooleanExtra
(ConnectivityManager.EXTRA_NO_CONNECTIVITY, Boolean.FALSE))
{
// no Internet connection,send network state changed
Bus.post(newNetworkStateChanged(false));
}
}
// 事件
public class NetworkStateChanged {
private mIsInternetConnected;
public NetworkStateChanged(boolean isInternetConnected) {
this.mIsInternetConnected = isInternetConnected;
}
public boolean isInternetConnected() {
return this.mIsInternetConnected;
}
}
public class MainActivity extends Activity {
public static Bus bus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bus = new Bus();
bus.register(this); // register Otto event Bus
}
@Override
protected void onDestroy() {
super.onDestroy();
bus.unregister(this); // unregister Otto event Bus
}
//Method that will be called when someone posts an event NetworkStateChanged
public void onEventMainThread(NetworkStateChanged event) {
if (!event.isInternetConnected()) {
Toast.makeText(this, "No Internet connection!", Toast.LENGTH_SHORT).show();
}
}
}
正如我先说,Otto(事件总线)允许你直接连接这些类。 你可以有一个事件从类A通知类B与唯一的中介本身。 但是在采用RxJava之后,我认为Rx和事件总线都使用反应模式,而RxJava则更好。 所以我们可以说再见事件总线。 这是一个RxJava作为事件总线的实现:
public class RxBus {private final Subject<Object, Object> bus = new SerializedSubject<>(PublishSubject.create());
public void post(Object o) {
bus.onNext(o);
}
// Subscribe to this Observable. to get it
public Observable<Object> getEvents() {
return bus;
}
}
// Subscribe to the event
getEvents().subscribe(new Action1<Object>() {
@Override
public void call(Object o) {
if(o instanceof AnswerEvent){
// TODO
}
}
});
这是一种使用Java 8 Lambdas到Java 6/7(以及Android)的方法。 使你的代码更清洁,结合它与RxJava和你是坚实的。 这是所有你需要包括它:
classpath 'me.tatarka:gradle-retrolambda:x.y.z'
apply plugin: 'me.tatarka.retrolambda'
下面是一个简单的例子如何使用Retrolambda & RxJava
Observable.just("Hello, world!")
.subscribe(s -> System.out.println(s));
是啊! 清洁和简洁的代码。
Dagger 2是著名的Dagger依赖注入库的继承者,我强烈推荐它。 其中一个主要的改进是在生成的注入代码中使用零反射,这使得调试更容易。
Dagger创建你的类的实例,并满足他们的依赖。 它依赖于javax.inject.Inject注释来标识哪些构造函数或字段应被视为依赖关系。 让我们来看看这个着名的CoffeeMaker示例:class Thermosiphon implements Pump {
private final Heater heater;
@Inject
Thermosiphon(Heater heater) {
this.heater = heater;
}
...
}
An example with direct injection into fields:
class CoffeeMaker {
@Inject Heater heater;
@Inject Pump pump;
...
}
Dependencies are provided via modules and @Provides annotation from Dagger:
@Module
class DripCoffeeModule {
@Provides
Heater provideHeater() {
return new ElectricHeater();
}
@Provides
Pump providePump(Thermosiphon pump) {
return pump;
}
}
要使用它添加到build.gradle文件:
compile 'com.google.dagger:dagger:x.y.z'
compile 'org.glassfish:javax.annotation:10.0-b28'//annotation Dagger compile 'com.google.dagger:dagger-compiler:x.y.z'//Dagger compiler
是Android中的另一种类型的数据库。 但是,非常重要的是,Realm不使用SQLite。 如果使用ORMLite或ActiveAndroid或任何其他类似的库,您的数据存储在SQLite数据库中,因为这些库给我们在SQLite上只有一个覆盖。 与Realm它是完全不同的是没有SQLite。 这就是你需要使用它:classpath 'io.realm:realm-gradle-plugin:x.y.z'
//
apply plugin: 'realm-android'
这里有一个非常简单的例子如何使用它:
public class Book extends RealmObject {
@Required
private String title;
public String getTitle() {
return title;
}
public void setTitle(final String title) {
this.title = title;
}
}
// MAIN_ACTIVITY
public class MainActivity extends Activity {
private Realm mRealm;
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mRealm = Realm.getInstance(getContext());
}
@Override
public void onDestroy() {
super.onDestroy();
mRealm.close();
}
// Example of add/ remove a book
@OnClick(R.id.add)
public void onAddClick() {
mRealm.beginTransaction();
Book book = mRealm.createObject(Book.class);
book.setTitle(getTrimTitle());
mRealm.commitTransaction();
}
@OnClick(R.id.remove)
public void onRemoveClick() {
mRealm.beginTransaction();
RealmResults<MyBook> books = mRealm.where(Book.class)
.equalTo("title",getTrimTitle())
.findAll();
if(!books.isEmpty()) {
for(int i = books.size() - 1; i >= 0; i--) {
books.get(i).removeFromRealm();
}
}
mRealm.commitTransaction();
}
private String getTrimTitle() {
return mEditTitle.getText().toString().trim();
}
}
ViewPropertyAnimator在API级别12引入,允许您使用单个Animator实例简单高效地对多个视图属性执行动画操作(并行)。 对我们来说实现程序化是简单和整洁的:
// Animate Button
mButton.animate()
.alpha(1f)
.scaleX(1f)
.scaleY(1f)
.translationZ(10f)
.setInterpolator(new FastOutSlowInInterpolator())
.setStartDelay(200)
.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) { }
@Override
public void onAnimationEnd(Animator animation) { }
@Override
public void onAnimationCancel(Animator animation) { }
@Override
public void onAnimationRepeat(Animator animation) { }
})
.start();
转换框架
Android转换框架允许您配置应用程序用户界面中的更改的外观。 它提供工具,以有效地管理和导航生活的过渡。 这个框架有一些限制:
应用于SurfaceView的动画可能无法正确显示。 SurfaceView实例从非UI线程更新,因此更新可能与其他视图的动画不同步。
一些特定的过渡类型在应用于TextureView时可能不会产生所需的动画效果。
扩展AdapterView的类(如ListView)以与转换框架不兼容的方式管理其子视图。 如果尝试对基于AdapterView的视图进行动画处理,则设备显示可能会挂起。
如果您尝试使用动画调整TextView的大小,则在对象完全调整大小之前,文本将会弹出到新位置。 要避免此问题,请不要对包含文本的视图的大小调整进行动画处理。