Here is my definition:
public abstract class APICallback<T extends CommonModel.APIDataModel> implements Callback<CommonModel<T>>
I found that I can not convert APICallback back to Callback.
What is the problem?
How can I do it correctly?
Thank you!
----Update----
In fact I am using retrofit, I defined APICallback implements retrofit.Callback
Here is the exact code :
public abstract class APICallback<T extends CommonModel.APIDataModel> implements Callback<CommonModel<T>> {
private Context context;
public APICallback(Context context) {
this.context = context;
}
public abstract void onResponse(T response);
#Override
public void onResponse(Response<CommonModel<T>> response, Retrofit retrofit) {
T data = response.body().data;
if (response.body().isSuccess()) {
onResponse(data);
onEnd();
} else {
dispatchError(response.body());
}
}
#Override
public void onFailure(Throwable t) {
LogUtils.d("Network error or exception", t.getMessage());
ViewUtils.showMessage(t.getMessage());
onEnd();
}
public void dispatchError(CommonModel<T> response) {
LogUtils.d("API error", response.toString());
ViewUtils.showMessage(response.data.msg);
onEnd();
}
public void onEnd() {
if (context instanceof BaseActivity) {
((BaseActivity) context).getLoading().hide();
}
}
I am using it like this:
getClient().login(u, p).enqueue(new APICallback<UserModel>(this) {
#Override
public void onResponse(UserModel response) {
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
});
enqueue :
void enqueue(Callback<T> callback);
login :
Call<UserModel> login(#Field("user_name") String userName, #Field("user_password") String userPassword);
The compiler tell me that can not convert anonymous APICallback<UserModel> to Callback<UserModel>
I am confused.
I didn't notice that my login method definition doesn't match Callback<CommonModel<T>>.
After I change it to
Call<CommonModel<UserModel>> login(#Field("user_name") String userName, #Field("user_password") String userPassword);
everything is ok.
Related
I'm trying to create couple of Java class to perform certain work. Let's say I want to get the task done by calling my classes like this:
FirebaseAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "signInWithCredential:success");
FirebaseUser user = task.getResult().getUser();
// ...
} else {
// Sign in failed, display a message and update the UI
Log.w(TAG, "signInWithCredential:failure", task.getException());
if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
// The verification code entered was invalid
}
}
}
});
I could understand up to signInWithCredential(). I can't figure out how to implement addOnCompleteListener() and have a interface as argument.
I've currently create my top class like FirebaseAuth with methods like getInstance () and signInWithCredential(). Also, I tried creating an interface but I am getting error that result of the interface is never used. How can I implement the style of addOnCompleteListener(parameter 1, interface 2).
Here, addOnCompleteListener is getting parameters of activity and interface and in my case, I will be using the activity parameter for some work.
P.S: I found out this is called interface callback. If it's right, any guidance to it's structure will be great
You can do it like this:
Create an interface:
public interface onCompleteListener {
void onComplete(MyTask object);
}
Define your MyTask class:
public abstract class MyTask {
public abstract boolean someFunc1();
public abstract String someFunc2();
public abstract String someFunc3();
}
In your main class:
public class MainClass{
public static MainClass instance;
private static Activity mActivity;
public onCompleteListener onCompleteListener;
private MainClass(Activity activity) {
mActivity = activity;
}
public static synchronized MainClass getInstance(Activity activity) {
if (instance == null) {
instance = new MainClass(activity);
}
return instance;
}
public void addOnCompleteListener(#NonNull onCompleteListener var2) {
onCompleteListener = var2;
//Call your task function
doTask();
}
public void doTask(){
MyTask o = new MyTask() {
#Override
public boolean someFunc1() {
return true;
}
#Override
public String someFunc2() {
return "";
}
#Override
public String someFunc3 {
return "";
}
};
//Once done, pass your Task object to the interface.
onCompleteListener.onComplete(o);
}
}
Usage:
MainClass.getInstance(MainActivity.this).addOnCompleteListener(new onCompleteListener() {
#Override
public void onComplete(MyTask object) {
doYourWork(object);
}
});
I am trying to create my own retrofit callback handler because I want to hide a loading screen once the call is done and would rather not repeat the call. I'm getting a Unchecked Assignment warning when using my custom RetrofitCallback and not retrofit2.Callback. What is the correct way to fix this warning?
public abstract class RetrofitCallback<T> implements Callback {
private BaseActivity mContext;
public RetrofitCallback(Context context) {
mContext = (BaseActivity) context;
}
#Override
public void onResponse(Call call, Response response) {
mContext.hideLoading();
onSuccess(response);
}
#Override
public void onFailure(Call call, Throwable t) {
mContext.hideLoading();
}
public abstract void onSuccess(#NonNull Response<T> response);
}
Call being made
service.getSignupCode(request).enqueue(new RetrofitCallback<SignupResponse>(this) {
#Override
public void onSuccess(#NonNull Response<SignupResponse> response) {
}
});
Can you try this below code?. The one mistake I can figure out is implementing Callback instead of Callback<T>
public abstract class RetrofitCallback<T> implements Callback<T> {
private BaseActivity mContext;
public RetrofitCallback(Context context) {
mContext = (BaseActivity) context;
}
#Override
public void onResponse(Call call, Response response) {
mContext.hideLoading();
onSuccess(response);
}
#Override
public void onFailure(Call call, Throwable t) {
mContext.hideLoading();
}
public abstract void onSuccess(#NonNull Response<T> response);
}
This is what I got to do
UploadCompleteListener is a custom interface that acts as a callback.
#Overrider
public Result doWork() {
mUpLoadDataService.uploadInspectionData(new UpLoadDataService.UploadCompleteListener() {
#Override
public void uploadComplete() {
return Result.success(); //this is what I want to do
}
#Override
public void uploadFailed(String reason) {
return Result.failure(); //this is what I want to do
}
});
return null;
}
Is it Possible?
If possible in any way please response soon. I can provide more details if you need it.
** This is what worked for me **
#NonNull
#Override
public Result doWork() {
final Result[] result = new Result[1];
mUpLoadDataService.uploadInspectionData(new UpLoadDataService.UploadCompleteListener() {
#Override
public void uploadComplete() {
result[0] = Result.success(); //this is what I want to do
}
#Override
public void uploadFailed(String reason) {
result[0] = Result.failure(); //this is what I want to do
}
});
return result[0];
}
public Result doWork(UpLoadDataService.UploadCompleteListener uploadListener) {
mUpLoadDataService.uploadInspectionData(uploadListener);
return null;
}
now pass the implementation from parent function. Lets say your parent function is named foobar
void foobar() {
someObject.doWork(new UpLoadDataService.UploadCompleteListener() {
#Override
public void uploadComplete() {
//write your logic here
return Result.success();
}
#Override
public void uploadFailed(String reason) {
//write your logic here
return Result.failure();
}
});
}
You have to realize that you are trying to get synchronously a result from an asynchronous call. This call is asynchronous for a reason, so the short answer is no, you can't.
Instead of returning a Result, you could return, for instance, a Future, which models the asynchronicity of the operation.
For android take a look at CallbackToFutureAdapter
https://developer.android.com/reference/kotlin/androidx/concurrent/futures/CallbackToFutureAdapter
https://developer.android.com/reference/java/util/concurrent/Future
You could use EventBus to notify Subscribed methods in every place you want like so:
public class MessageEvent {
public final String message;
public MessageEvent(String message) {
this.message = message;
}
}
public void doWork() {
mUpLoadDataService.uploadInspectionData(new UpLoadDataService.UploadCompleteListener() {
#Override
public void uploadComplete() {
EventBus.getDefault().post(new MessageEvent("success"));
}
#Override
public void uploadFailed(String reason) {
EventBus.getDefault().post(new MessageEvent("failed"));
}
});
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}
See this implementation guide.
You can get the callback of your task using the following way
doWork(paremter, new ServiceListener<String>() { //paremter if any
#Override
public void success(String obj) {
//get the response if success
}
#Override
public void fail(ServiceError error) {
//get the error response
}
});
do the work and send the call response from where it called
private void doWork(String param , ServiceListener<String> serviceListener) {
mUpLoadDataService.uploadInspectionData(new UpLoadDataService.UploadCompleteListener() {
#Override
public void uploadComplete() {
serviceListener.success("success");
}
#Override
public void uploadFailed(String reason) {
serviceListener.fail(new ServiceError("Can not Upload"));
}
});
}
ServiceListener interface will be defined as follow
public interface ServiceListener<T> {
void success(T obj);
void fail(ServiceError error);
}
public class ServiceError {
public Throwable errorObject;
public String message;
public ServiceError(){
message = "";
}
public ServiceError(String message){
this.message = message;
}
public ServiceError(String message, Throwable errorObject){
this.message = message;
this.errorObject = errorObject;
}
public Object getErrorObject() {
return errorObject;
}
public void setErrorObject(Throwable errorObject) {
this.errorObject = errorObject;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
I am trying to test functions from my Presenter Class. In below, I can reach getSomeThing() function however, I cannot reach the getData() and getError() functions.
Volley functions are not working in unit tests. Further help would be highly appreciated as I am struggling with this for over a week.
Below is my Presenter Class, Presenter Listener and Test Function.
my Presenter Class:
public abstract class SomePresenter implements BasePresenterListener {
private static final String sTAG = SomePresenter.class.getSimpleName();
private Context context;
private Integer testInteger;
protected SomePresenter(Context context, Integer testInteger) {
this.context = context;
this.testInteger = testInteger;
onResponse();
}
#Override
public void onResponse() {
try {
Thread.sleep(1000);
getSomeThing();
} catch (InterruptedException e) {
e.printStackTrace();
}
final GetRequest<SomeResponse> someResponseRequest =
ApiRequests.getSomeResponse(
new Response.Listener<SomeResponse>() {
#Override
public void onResponse(SomeResponse response) {
getData(response);
}
}
,
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setMessage(Constant.NETWORK_ERROR);
getError(errorResponse);
}
}
);
NetworkInstance.addRequest(context, poiResponseGetRequest, sTAG);
}
public static void cancelRequest(Context context) {
NetworkInstance.cancelAllRequests(context, sTAG);
}
protected abstract void getSomeThing();
protected abstract void getData(SomeResponse response);
protected abstract void getError(ErrorResponse response);
}
my BasePresenter Class:
public interface BasePresenterListener {
void onResponse();
}
my Unit Test Function:
#Test
public void test() throws InterruptedException {
new SomePresenter(mockContext, 107){
#Override
protected void getData(PoiResponse response) {
SomeLogger.debug("getData works");//this is not called.
}
#Override
protected void getSomeThing() {
SomeLogger.debug("getSomeThing works!");//this is called.
}
#Override
protected void getError(ErrorResponse response) {
SomeLogger.debug("ErrorResponse works!"); //this is not called.
}
};
}
I have looked below links none of them solved my problem.
Unit testing a network response. Works when debugging, not when actually running
Android Unit test with Volley
In my case is I can reach the getSomething() function from unit test but I cannot reach the getData() nor getError() functions because Volley does not seem to work in unit tests.
All, getSomething(), getData(), getError() functions are callback functions, I can reach the getSomeThing() function but I cannot reach the getData() and getError() functions.
Hello I recently started retrofit While implementing the code im getting this error
Incompatible types.
Required: retrofit2.Call <java.util.List<com.my.package.Youtube.YoutubePost>>
Found: void
I was trying to get YouTube channel playlist using Youtube v3 API
This is my code for the same
YoutubeActivity
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create())
.baseUrl(AppConstant.API_YT_BASE)
.addConverterFactory(GsonConverterFactory.create())
.build();
YoutubeApiInterface youtubeApiInterface = retrofit.create(YoutubeApiInterface.class);
Call<List<YoutubePost>> call = youtubeApiInterface.getPlayList().enqueue(new Callback<List<YoutubePost>>() {
#Override
public void onResponse(Call<List<YoutubePost>> call, Response<List<YoutubePost>> response) {
if (response.isSuccessful()) {
} else {
}
}
#Override
public void onFailure(Call<List<YoutubePost>> call, Throwable t) {
t.printStackTrace();
}
});
YoutubePost
public class YoutubePost implements Parcelable {
#SerializedName("items")
private List<YoutubeItems> ytItems = new ArrayList<>();
private String nextPageToken;
public List<YoutubeItems> getYtItems() {
return ytItems;
}
public String getNextPageToken() {
return nextPageToken;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeList(ytItems);
dest.writeString(nextPageToken);
}
protected YoutubePost(Parcel in) {
ytItems = in.readParcelable(YoutubeItems.class.getClassLoader());
nextPageToken = in.readString();
}
public static final Creator<YoutubePost> CREATOR = new Creator<YoutubePost>() {
#Override
public YoutubePost createFromParcel(Parcel source) {
return new YoutubePost(source);
}
#Override
public YoutubePost[] newArray(int size) {
return new YoutubePost[size];
}
};
}
Screenshot of error message attached below
I suggest you, to modify the getPlayList method a little bit, to return with a Call, then break the lines.
Without your YoutubeApiInterface this is all I got.
Call<List<YoutubePost>> call = youtubeApiInterface.getPlayList();
call.enqueue(new Callback<List<YoutubePost>>() {
#Override
public void onResponse(Call<List<YoutubePost>> call, Response<List<YoutubePost>> response) {
if (response.isSuccessful()) {
} else {
}
}.
#Override
public void onFailure(Call<List<YoutubePost>> call, Throwable t) {
t.printStackTrace();
}
});
By this you won't have a type problem, because the call itself will be modified, during the enqueue.