LoginSignup
5
5

More than 5 years have passed since last update.

【Android】SwiftからのAndroid③ Ajax通信時のコールバックについて

Last updated at Posted at 2015-08-04

javaでは関数がクロージャを受け取ることができない

ようですね。
SwiftではAjax通信完了時の処理ブロックをそのまま渡すだけだったんですが、Androidではそういう書き方ができませんでした。

【Swift】AlamofireでWEBAPIにアクセスするfunc
この関数を持ってるクラスを継承してinitでcolumnsに列設定、apiURLを上書きして使ってました。

Model.swift
/*
apiURLに対してGET処理を行う
columnsに追加されている列をrecordsに取得する
*/
var apiURL:String = "http://hogehoge.com/"
var whereParam:[String:AnyObject] = Dictionary()
var updateParam:[String:AnyObject] = Dictionary()
var columns:[String] = Array()
var records:[[String:AnyObject]] = Array()
var isError = false

func get(whereParam:[String:AnyObject]?,callback:(() -> Void)!){
    isError = false
    records = Array()
    Alamofire.request(.GET, apiURL, parameters:whereParam)
        .validate(statusCode: 200..<400)
        .responseJSON { (request, response, json, error) in
            self.records.removeAll(keepCapacity: false)
            if response == nil {
                self.isError =  true
                callback();
                return
            }

            if error != nil {
                self.isError =  true
                callback();
                return
            }

            var record:[String:AnyObject] = Dictionary()

            for item in json as! NSArray {
                for column in self.columns {
                    if item.objectForKey(column) != nil{
                        record[column] = self.nullToNil(item[column])
                    }
                }
                if(record.count > 0){
                    self.records.append(record)
                }

            }

            callback();
    }
}

【Swift】具体的なテーブルとURLを設定
Columns.Table.ColumnNm はpublic static let で定義

user.swift
class User:Model{

    let API:String = "users"

    override init(){
        super.init()

        /* 列設定 */
        self.columns.append(Columns.User.ID)
        self.columns.append(Columns.User.NAME)

        /* API URLの更新 */
        self.apiURL += API
    }

}

【Swift】利用時

viewController.swift
var user = User()
self.user.whereParam[Columns.User.ID] = 1
user.get({
    println("コールバック部分")
})

実際apiURLはmobileBackendのデータストアからURLを引っ張ってきてinitで設定してます。
あとpost、deleteも作ってあります。
alamofireはmultipartでのファイル送信ができないから、ファイルのupload処理は別に作ってますが・・・

これでAPI側の口さえあれば
スペルミス防止のためのColumns.Table.ColumnNmとModelクラスを継承したクラスを作ればアクセス可能になります。

って感じでしてたのをAndroidに移行しようと思ったんですが、なかなかすんなりできなかったので対応方法をメモ

結局こんな感じになった

問題点としては
・ひとつのクラスで複数のコールバックをするので、Activityでコールバックインターフェースを実装するのは微妙
・複数のAjax通信がかぶるとコールバックが上書きされる可能性がある

なのでajax通信するオブジェクトはフィールド変数にしない ⇨ メモリ消費しそうだけどしょうがない
Activityで実装しないで処理を都度overrideする ⇨ よく使うコールバックとかがあるときはまた考える

【Android】volleyでWEBAPIにアクセスするmethod

Model.java
public class Model {

    public interface ResponseCallback {
        public void callbackMethod();
    }

    private RequestQueue queue;
    protected String apiURL = "";
    public HashMap<String,String> whereParam = new HashMap<String,String>();
    public HashMap<String,String> updateParam = new HashMap<String,String>();
    public ArrayList<String> columns = new ArrayList<String>();
    public int id;
    public boolean isError = false;
    public JSONArray resJSONArray;
    public JSONObject resJSONObject;

    public Model(){
        apiURL = "http://hogehoge.com";
    }

    private ResponseCallback callback;
    public void setResponseCallback(ResponseCallback callback){
        this.callback = callback;
    }

    /*
    apiURLに対してGET処理を行う
    columnsに追加されている列をresJSONArrayに取得する
    */
    public void get(HashMap<String,String> whereParam,final Context context) {

        isError = false;
        resJSONArray = null;
        resJSONObject = null;
        queue = Volley.newRequestQueue(context);

        JsonArrayRequest getRequest = new JsonArrayRequest(
                Request.Method.GET,
                apiURL + createParameter(whereParam),
                (String) null,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        try {
                            resJSONArray = response;
                            callback.callbackMethod();
                        } catch (Exception e) {
                            CustomProgress.hideProgress();
                            isError = true;
                        }
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        isError = true;
                        Toast.makeText(context, "エラー", Toast.LENGTH_SHORT).show();
                        return;
                    }
                });
        queue.add(getRequest);
    }
}

【Android】具体的なテーブルとURLを設定

User.java
public class User extends Model {

    private final String API = "users";

    public User(){
        super();
        this.columns.add(Columns.User.ID);
        this.columns.add(Columns.Composition.NAME);
        /* API URLの更新 */
        this.apiURL += API;
    }
}

【Android】Modelに処理を移譲するための空クラス

AjaxCallback.java
public class AjaxCallback implements Model.ResponseCallback{
    public void callbackMethod(){

    }
}

【Android】利用時

Activity.java
final Composition composition = new Composition();
CustomProgress.showProgress(this);
composition.setResponseCallback(new AjaxCallback(){
    @Override
    public void callbackMethod(){
        Log.d("IN CALLBACK","コールバック部分");
    }
});

なんかもっといい感じにならないかなぁ

参考

http://qiita.com/KeithYokoma/items/d6c3bd07fc57b93f91cc
http://qiita.com/__zck__/items/86c0a7ab9de4f79eacdb

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5