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

##javaでは関数がクロージャを受け取ることができない
ようですね。
SwiftではAjax通信完了時の処理ブロックをそのまま渡すだけだったんですが、Androidではそういう書き方ができませんでした。

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

```swift: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 で定義

```swift: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】利用時

```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

```java: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を設定

```java: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に処理を移譲するための空クラス

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

    }
}
```

【Android】利用時

```java: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