<< Java interface 예제 (json을 이용한 서버 연동) >>
1. 사용 목적
안드로이드단말에서 json을 이용한 서버 연동시 여러곳에서 할 수 있고, 그 결과도 요청한 곳에서 받아야 한다.
그렇다고 해서 각각의 보내는곳에서 똑같은 코딩을 반복되게 할 수는 없는 노릇이다.
그래서 옛날에는 callback 방식으로 결과를 받기도 했지만, interface를 이용하여 결과를 받는것이 더 깔끔하고 편하다.
2. 서버로 요청 할때
사용예)
NewsRequestParam requestParam = new NewsRequestParam();
requestParam.setUserId("androi");
requestParam.setUserType("special");
requestParam.setNewsCategory("sports");
Sender sender = new JsonSender(this); // implements Receiver 이므로 this 가능, 또는 mActivity
sender.send(requestParam);
3. 서버에서 결과를 받을때 ( Receiver 를 구현한다)
사용예)
public class MyMain extends Activity implements Receiver
{
private MyMain mActivity = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mymain);
mActivity = this;
}
...
@Override
public void update(ResponseEvent response) { // 결과가 여기로 온다. 아래는 샘플
if (response.getResultCode() == 0) {
String resultText = response.getResultData();
ResultVOType voType = null;
try {
JSONObject jsonObject = new JSONObject(resultText);
String voTypeText = jsonObject.getString("resultVOType");
if (!voTypeText.isEmpty() && voTypeText.equals("null") == false) {
voType = ResultVOType.valueOf(voTypeText);
String data = jsonObject.getString("data");
System.out.println("[VMS] " + voType.name().toString() + ", " + data);
switch (voType) {
case VMS_FURNITURE_ITEM_LIST: // 상품목록 수신
VMSItemVOList itemVOList = new Gson().fromJson(data, VMSItemVOList.class);
resultVMSItemData(itemVOList);
break;
case VMS_FURNITURE_ITEM_SIZE: // 상품 사이즈 수신
VMSItemData itemVO = new Gson().fromJson(data, VMSItemData.class);
resultVMSItemVO(itemVO);
break;
case VMS_FURNITURE_ITEM_SAVE: // 상품 전송 결과
String resultCode = jsonObject.getString("code");
if (resultCode.equals("0")) {
DialogUtils.showToast(mContext, "전송이 성공하였습니다.");
} else {
String resultMessage = jsonObject .getString("message");
DialogUtils.showToast(mContext, "전송이 실패하였습니다. ("+ resultCode + ", " + resultMessage + ")");
}
break;
default:
break;
}
}
} catch (JSONException e) {
}
} else {
Log.e(TAG, " : 데이터 수신 실패");
}
}
...
}
4. Receiver 인터페이스
update 메서드 구현을 강제한다.
public interface Receiver {
public void update(ResponseEvent response);
}
4. Sender 인터페이스와 JsonSender 클래스
왜 sender.send();로 요청했는데, update()로 결과가 오는걸까??
이걸 알아보기 위해서는 Sender가 무엇인지 먼저 확인을 해야한다. 아래처럼 send() 메서드를 가지고 있는 interface 이다.
public interface Sender {
public void send(RequestParam requestParam);
}
가장 중요한 JsonSender는 어떻게 구성되어 있을까? Sender interface를 구현하고 있다. 또한 생성자에 this값을 받아서 리시버를 등록한다.
public class JsonSender implements Sender {
private ResponseListener responseListener;
public JsonSender(Receiver receiver) {
this.responseListener = new JsonResponseResult(receiver);
}
@Override
public void send(RequestParam requestParam) {
// 실제 서버로 Json 데이터를 보내는 부분, responseListener 리스너를 전달한다.
RealSendServer srv = new RealSendServer(requestParam, responseListener)
}
}
5. JsonResponseResult 클래스 ( ResponseListener 구현 )
서버로 전송한 결과를 1차로 받는곳. receive()에서 받음. receiver.update(response)를 호출하여, 3번의 update()에서 결과를 받도록 한다.
public class JsonResponseResult implements ResponseListener{
private static final String TAG = "JsonResponseListener";
private Receiver receiver;
public JsonResponseResult(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void receive(ResponseEvent response) {
Log.d(TAG, "result code ========> "+response.getResultCode());
Log.d(TAG, "result data ========> "+response.getResultData());
if(response.getResultCode() != 0){
Log.e(TAG,"데이터 수신 실패");
}
receiver.update(response);
}
}
6. ResponseListener 인터페이스
public interface ResponseListener{
public void receive(ResponseEvent response);
}
7. RealSendServer 클래스
public class RealSendServer {
private static ResponseListener mResponseListener;
private ResponseEvent response = null;
private RequestParam requestParam = null;
public RealSendServer(RequestParam requestParam, ResponseListener listener) {
mResponseListener = listener;
// requestParam 을 이용하여 Json 전송
String reqParam = requestParam.buildParam(); // TODO
Log.d("JsonSender Parameter ====>", reqParam);
this.requestParam = requestParam;
new GetResponse().execute();
}
private void afterRealSend(){
// 값을 전달하고, 결과값을 받았을때
if(mResponseListener != null){
mResponseListener.receive(response)
}
}
private class GetResponse extends AsyncTask<String, Integer, Long> {
@Override
protected Long doInBackground(String... params) {
// Creating JSON Parser instance
JSONParser jParser = new JSONParser();
// getting JSON string from URL
JSONObject json = jParser.getJSONFromUrl(requestParam.getUrl()); // TODO
int code = -1;
if(json != null){
code = 0;
}
response = new ResponseEvent();
response.setResultCode(code);
response.setResultData(json);
return null;
}
@Override
protected void onPostExecute(Long result) {
super.onPostExecute(result);
afterRealSend();
}
}
}
8. 좀 복잡하죠.. 여기서 사용한 인터페이스에 대해서 잘모르겠다면 좀더 간단한 아래 링크 참조
http://androi.tistory.com/113
9. RequestParam 추상 클래스
서버로 데이터를 요청할때도 여러 종류의 데이터를 전송하는데, 그 중에서 공통되는것들을 추상클래스로 정의한다.
public abstract class RequestParam {
Map<String, Object> paramMap = new HashMap<String, Object>();
private String userId = "";
private String userType = "";
private String versionName = "";
protected void add(String key, Object val) {
paramMap.put(key, val);
}
/**
* paramMap 을 string 으로 변환
*/
public abstract String buildParam();
public Map<String, Object> getParamMap() {
return paramMap;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType;
}
public String getVersionName() {
return versionName;
}
}
10. NewsRequestParam 클래스 (RequestParam 추상 클래스를 상속받은 클래스, buildParam()을 구현했다.)
뉴스 제목만을 가져오는 예
public class NewsRequestParam extends RequestParam {
private String category = "";
public String getNewsCategory() {
return category;
}
public void setNewsCategory(String category) {
this.category = category;
}
@Override
public String buildParam() {
return new Gson().toJson(this);
}
}
11. ResponseEvent
public class ResponseEvent {
private int resultCode = -1;
private String resultData = "";
public int getResultCode() {
return resultCode;
}
public void setResultCode(int resultCode) {
this.resultCode = resultCode;
}
public String getResultData() {
return resultData;
}
public void setResultData(String resultData) {
this.resultData = resultData;
}
}
12. JSONParser 객체
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
public class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
// constructor
public JSONParser() {}
public JSONObject getJSONFromUrl(String url) {
// Making HTTP request
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"), 8); // iso-8859-1
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
json = sb.toString();
Log.e("JSON", json); // TODO
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
// try parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
// return JSON String
return jObj;
}
}
'안드로이드 개발 팁' 카테고리의 다른 글
안드로이드 카메라 갤러리 연동 (0) | 2014.08.19 |
---|---|
[android] open source library 비교 분석. (0) | 2014.08.13 |
안드로이드 리소스 동적으로 호출(소스에서 호출) (0) | 2014.07.21 |
안드로이드 ExpandableListView 구현 관련 (0) | 2014.07.15 |
안드로이드 레디오 버튼 버튼배경 바꾸기 (0) | 2014.07.15 |