След дълга борба с генеричните продукти и изтриването на типове, най-накрая го направих.
Така че публикувам това за всеки, който има същия проблем като мен и се нуждае от решение, без да се побърква.
Моят ErrorEntity и моят SuccessfulEntity все още са същите, но създадох нов интерфейс, наречен RepositoryListener, като този:
public interface RepositoryListener {
public abstract void onErrorResponse(int code, String details);
public abstract void onSuccessfulResponse(int code, Object obj);
public abstract void onSuccessfulResponse2(int code, List<Object> obj);
}
След това направих клас, VolleyRestClient, като този:
public class VolleyRestClient extends RestClient {
private final DefaultRetryPolicy mRetryPolicy;
private final RequestQueue mQueue;
private final Gson gson = new Gson();
public VolleyRestClient(Context context) {
// Default retry policy
mRetryPolicy = new DefaultRetryPolicy(2000, 3, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
mQueue = Volley.newRequestQueue(context);
}
public RequestQueue getQueue() {
// Method to push requests for image download
return mQueue;
}
@Override
public void GET(boolean obj, boolean needAuth, String url, Type type,
RepositoryListener listener) {
// Choose which listener to construct
Response.Listener<myResponse> mListener = obj ?
// This uses objects
makeSuccessfulListener(listener, type) :
// This uses list of objects
makeSuccessfulListener2(listener, type);
myRequest mRequest =
new myRequest(Request.Method.GET, needAuth, url,
mListener, makeErrorListener(listener));
mRequest.setRetryPolicy(mRetryPolicy);
mQueue.add(mRequest);
}
@Override
public void POST(boolean needAuth, String url, String body, Type type, RepositoryListener listener) {
myRequest mRequest = new myRequest(Request.Method.POST, needAuth, url, body,
makeSuccessfulListener(listener, type), makeErrorListener(listener));
mRequest.setRetryPolicy(mRetryPolicy);
mQueue.add(mRequest);
}
@Override
public void DELETE(boolean needAuth, String url, Type type, RepositoryListener listener) {
myRequest mRequest =
new myRequest(Request.Method.DELETE, needAuth, url,
makeSuccessfulListener(listener, type), makeErrorListener(listener));
mRequest.setRetryPolicy(mRetryPolicy);
mQueue.add(mRequest);
}
private Response.Listener<myRequest> makeSuccessfulListener
(final RepositoryListener listener, final Type type) {
// TODO: test this method and implement lists
if (listener == null) {
return null;
} else {
return new Response.Listener<myRequest>() {
@Override
public void onResponse(myRequest response) {
SuccessfulEntity<Object> obj = gson.fromJson(response.getBody(), type);
listener.onSuccessfulResponse(response.getCode(), obj.getData());
}
};
}
}
private Response.Listener<myRequest> makeSuccessfulListener2
(final RepositoryListener listener, final Type type) {
// TODO: test lists
if (listener == null) {
return null;
} else {
return new Response.Listener<myRequest>() {
@Override
public void onResponse(myReqyest response) {
SuccessfulEntity<List<Object>> obj = gson.fromJson(response.getBody(), type);
listener.onSuccessfulResponse2(response.getCode(), obj.getData());
}
};
}
}
private Response.ErrorListener makeErrorListener(final RepositoryListener listener) {
return new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
try {
String jError = new String(error.networkResponse.data);
ErrorEntity mError = gson.fromJson(jError, ErrorEntity.class);
// Invoke listener closure
listener.onErrorResponse(error.networkResponse.statusCode, mError.getDetails());
} catch (Exception e) {
listener.onErrorResponse(404, e.getMessage());
}
}
};
}
}
Това много зависи от моите нужди, но ще обясня общата концепция.
Така че имам персонализирана заявка, както е обяснено в моя въпрос, и искам да я анализирам до правилния тип данни.
За да бъда по-конкретен, бих могъл да имам данни за JSONArray само при GET заявки (странирани елементи и т.н...), така че трябва да намеря начин да разгранича тези два случая (разбира се, знам в кои случаи ще получа списък или обект).
Не можем просто да създадем POJO от Json в рамките на общ клас, използвайки неговия тип (защото Java Type Erasure), така че имаме нужда от тип обект предварително.
Но това, което можем да направим е:
в нашата персонализирана заявка, на parseNetworkResponse, направете нещо подобно:
@Override
protected Response<myResponse> parseNetworkResponse(NetworkResponse response) {
try {
// Using server charset
myResponse mResponse = new myResponse();
mResponse.setCode(response.statusCode);
mResponse.setBody(new String(response.data,
HttpHeaderParser.parseCharset(response.headers)));
// Return new response
return Response.success(mResponse, HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
// Normally use 'utf-8'
return Response.error(new ParseError(e));
}
}
С други думи, копирайте тялото на необработения низов отговор върху нов обект myResponse;
Тялото на отговора в крайна сметка ще бъде анализирано във VolleyRestClient със съответния тип, подаден като аргумент GET/DELETE/POST;
makeSuccessfulListener и makeSuccessfulListener2 създават Response.Listener от RepositoryListener, който има 3 метода за замяна: onSuccessfulResponse за данни на обекти, onSuccessfulResponse2< /em> за списък с данни за обекти, onErrorResponse за 4XX/5XX грешки;
- Our data object/list will be parsed to more generics type (List and Object) and then passed to our custom listener RepositoryListener.
Пълен пример за този подход:
public void getNewLogin(String nickname, String password,
final TextView author, final TextView title, final TextView text) {
String json =
(new StringBuilder()
.append("{ \"nickname\": \"")
.append(nickname)
.append("\", \"password\": \"")
.append(password)
.append("\" }")).toString();
mRest.POST(false, "http://192.168.0.104:8000/api/session", json,
new TypeToken<SuccessfulEntity<Login>>(){}.getType(),
new RepositoryListener() {
@Override
public void onSuccessfulResponse2(int code, List<Object> obj) {
// Nothing happens here
}
@Override
public void onSuccessfulResponse(int code, Object obj) {
UserSession mInstance = UserSession.getInstance(null);
Login newLogin = (Login) obj;
title.setText(newLogin.getToken());
mInstance.setToken(newLogin.getToken());
Log.i("onSuccessfulResponse", mInstance.getToken());
Log.i("onSuccessfulResponse", mInstance.getmAuthorizationToken());
if (newLogin.getUser() != null) {
author.setText(newLogin.getUser().getNickname());
text.setText(newLogin.getUser().getUniversity());
}
}
@Override
public void onErrorResponse(int code, String error) {
Log.i("onErrorResponse", error);
}
});
mRest е обект VolleyRestClient, който изпълнява POST заявка до този адрес с Type, конструиран от Gson TypeToken (не забравяйте, че нашето тяло е SuccessfulEntity).
Тъй като със сигурност ще имаме данни за обект, просто ще заменим onSuccessfulResponse, ще прехвърлим обект с данни към същия тип T на SuccessfulEntity, използван в TypeToken, и ще свършим мръсната си работа.
Не знам дали бях ясен, този подход работи, ако някой от вас има нужда от разяснение, просто попитайте :)
person
Dan.see
schedule
15.12.2015
Entity<T>
, който ще има всички подпори отSuccessfulEntity<T>
иErrorEntity
... и ще направи пропове, които не са често срещани в тези класове, незадължителни ... и за проверка на грешки ще използватеentity.getError() != null
- person Selvin   schedule 14.12.2015