Android SDK 子类化指南

从 1.4.0 版本开始,我们为 Android SDK 添加了子类化支持,一个简单的指南如下。

子类化

AVOSCloud 希望设计成能让人尽快上手并使用。你可以通过 ParseObject.get 方法访问所有的数据。但是在很多现有成熟的代码中,子类化能带来更多优点,诸如简洁、可扩展性以及 IDE 提供的代码自动完成的支持等等。子类化不是必须的,你可以将下列代码转化:

AVObject shield = new AVObject("Armor");
shield.put("displayName", "Wooden Shield");
shield.put("fireproof", false);
shield.put("rupees", 50);

成这样:

Armor shield = new Armor();
shield.setDisplayName("Wooden Shield");
shield.setFireproof(false);
shield.setRupees(50);

子类化 ParseObject

创建一个 ParseObject 的子类很简单:

  • 首先声明一个子类继承自 Parseobject。
  • 添加 @AVClassName 注解。它的值必须是一个字符串,也就是你过去传入 ParseObject 构造函数的类名。这样以来,后续就不需要再在代码中出现这个字符串类名。
  • 确保你的子类有一个 public 的默认(参数个数为 0)的构造函数。切记不要在构造函数里修改任何 ParseObject 的字段。
  • 在你的应用初始化的地方,在调用 AVOSCloud.initialize() 之前注册子类 AVObject.registerSubclass(YourClass.class)

下列代码成功实现并注册了 ParseObject 的子类 Armor:

// Armor.java
import com.avos.avoscloud.AVClassName;
import com.avos.avoscloud.AVObject;

@AVClassName("Armor")
public class Armor extends AVObject {
}

// App.java
import com.avos.avoscloud.AVOSCloud;
import android.app.Application;

public class App extends Application {
  @Override
  public void onCreate() {
    super.onCreate();

    AVObject.registerSubclass(Armor.class);
    AVOSCloud.initialize(this, "{{appid}}", "{{appkey}}");
  }
}

访问器,修改器和方法

添加方法到 ParseObject 的子类有助于封装类的逻辑。你可以将所有跟子类有关的逻辑放到一个地方,而不是分成多个类来分别处理商业逻辑和存储/转换逻辑。

你可以很容易地添加访问器和修改器到你的 ParseObject 子类。像平常那样声明字段的 getter 和 setter 方法,但是通过 Parseobject 的 get 和 put 方法来实现它们。下面是这个例子为 Armor 类创建了一个 displayName 的字段:

// Armor.java
@AVClassName("Armor")
public class Armor extends AVObject {
  public String getDisplayName() {
    return getString("displayName");
  }
  public void setDisplayName(String value) {
    put("displayName", value);
  }
}

现在你就可以使用 armor.getDisplayName() 方法来访问 displayName 字段,并通过 armor.setDisplayName("Wooden Sword") 来修改它。这样就允许你的 IDE 提供代码自动完成功能,并且可以在编译时发现到类型错误。

各种数据类型的访问器和修改器都可以这样被定义,使用各种 get() 方法的变种,例如 getInt(), getAVFile(), 或者 getMap()。

如果你不仅需要一个简单的访问器,而是有更复杂的逻辑,你可以实现自己的方法,例如:

public void takeDamage(int amount) {
  // 递减 armor 的 durability 字段,并判断是否应该设置 broken 状态
  increment("durability", -amount);
  if (getDurability() < 0) {
    setBroken(true);
  }
}

初始化子类

你可以使用你自定义的构造函数来创建你的子类对象。你的子类必须定义一个公开的默认构造函数,并且不修改任何父类 ParseObject 中的字段,这个默认构造函数将会被 SDK 使用来创建子类的强类型的对象。

要创建一个到现有对象的引用,可以使用 AVObject.createWithoutData():

Armor armorReference = AVObject.createWithoutData(Armor.class, armor.getObjectId());

查询

你可以通过 AVObject.getQuery() 或者 AVQuery.getQuery 的静态方法获取特定的子类的查询对象。下面的例子就查询了用户能够购买的盔甲 (Armor) 列表:

AVQuery<Armor> query = AVObject.getQuery(Armor.class);
//rupees 是游戏货币
query.whereLessThanOrEqualTo("rupees", AVUser.getCurrentUser().get("rupees"));
query.findInBackground(new FindCallback<Armor>() {
  @Override
  public void done(List<Armor> results, AVException e) {
    for (Armor a : results) {
      // ...
    }
  }
});

ParseUser 的子类化

ParseUser 作为 ParseObject 的子类,同样允许子类化,你可以定义自己的 User 对象,不过比起 ParseObject 子类化会更简单一些,只要继承 ParseUser 就可以了:

import com.avos.avoscloud.AVObject;
import com.avos.avoscloud.AVUser;

public class MyUser extends AVUser {
    public void setNickName(String name) {
    this.put("nickName", name);
    }

    public String getNickName() {
    return this.getString("nickName");
    }
}

不需要添加 @ParseClassname 注解,所有 ParseUser 的子类的类名都是内建的 _User。同样也不需要注册 MyUser。

注册跟普通的 ParseUser 对象没有什么不同,但是登陆如果希望返回自定义的子类,必须这样:

MyUser cloudUser = AVUser.logIn(username, password,
            MyUser.class);