Error: RestAdapter(...) has private access in 'retrofit.RestAdapter' - java

I am trying to make a class the uses Retrofit to make some API calls.
public class RedditUtils {
private RestAdapter restAdapter;
private RedditApiService service;
private final String redditBaseUrl = "https://oauth.reddit.com";
public RedditUtils()
{
restAdapter = new RestAdapter().Builder().setEndpoint(redditBaseUrl).build();
service = restAdapter.create(RedditApiService.class);
}
public void fetchToken(String token)
{
service.getToken(token, new Callback<RedditAccessToken>() {
#Override
public void success(RedditAccessToken redditAccessToken, Response response) {
Log.d("RedditAccessToken", redditAccessToken.getAccessToken());
}
#Override
public void failure(RetrofitError error) {
Log.d("RedditAccessTokenFailed", error.toString());
}
});
}
}
When I set restAdapter equalt to new RestAdapter(), I get the error
RestAdapter(*long path name*) has private access in 'retrofit.RestAdapter'
I am not sure what would be causing this error and I haven't found anyone else with this issue. Any ideas on how to solve the error?

You aren't suppose to instantiate RestAdapter, hence why it has a private constructor.
Builder is a static internal class of the RestAdapter class. You can instantiate it like so:
new RestAdapter.Builder()

Related

Compilation error during calling methods containing Either and wildcards

I have problem with understanding how Java wildcard works in one particular case. Let's say I have class which represents generic response
public class MyResponse<T> {
private final int httpCode;
private final String message;
private final T data;
}
and resolver for that:
public class ResponseResolver {
public void resolve(Either<AppError, MyResponse<?>> responseToResolve) {
//some logic
}
public void resolveOption(Option<MyResponse<?>> responseToResolve) {
//some logic
}
}
and service where response is resolved with resolver
public class FooService {
private final ResponseResolver responseResolver;
public FooService(ResponseResolver responseResolver) {
this.responseResolver = responseResolver;
}
public void resolveFoo() {
Either<AppError, MyResponse<Foo>> either = Option.of(new MyResponse<>(200, "message", new Foo())).toEither(AppError.ERROR);
responseResolver.resolve(either);
}
public void resolveOptionFoo() {
MyResponse<Foo> foo = new MyResponse<>(200, "message", new Foo());
responseResolver.resolveOption(Option.of(foo));
}
}
I do not understand why resolveOption method which is called in resolveFooOption is a proper way but in method with Either compiler complies that required type is Either<AppError, MyResponse<?> but provided Either<AppError, MyResponse<Foo>. Can anybody explain me why second case is invalid?

Problem passing parameters in Retrofit api using POST method

I want to get notifications from a server using API. I'm using Retrofit2 to work with API.
The problem is when I'm passing parameter in POST method I'm getting "IllegalArgumentException URL does not contain the parameter."
The parameter is correct and working in iOS. I want to implement in android.
Below is the result when debugging the app.
Caused by: java.lang.IllegalArgumentException: URL
"notification/newnotification" does not contain "{userid}". (parameter #1)
I've tried changing parameters and asked the API developer too. He says parameter is correct.
This is code for API Interface:
public interface API{
#FormUrlEncoded
#POST("notification/newnotification")
Call<ResponseBody> getUserNotification(
#Path("userid") int userid
);
}
RetrofitClient.java
public class RetrofitClient {
public static final String BASE_URL = "http://danceglobe.co/dance/api/";
private static RetrofitClient mInstance;
private Retrofit retrofit;
private RetrofitClient(){
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
public static synchronized RetrofitClient getInstance(){
if(mInstance == null) {
mInstance = new RetrofitClient();
}
return mInstance;
}
public API getApi(){
return retrofit.create(API.class);
}
}
Calling Function from MainActivity
private void getNotification(String currentUserId) {
Call<ResponseBody> call = RetrofitClient.getInstance().getApi().getUserNotification(Integer.parseInt(currentUserId));
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if(!response.isSuccessful()){
Toast.makeText(MainActivity.this,response.message(),Toast.LENGTH_SHORT).show();
}
try {
String s = response.body().string();
Toast.makeText(MainActivity.this,s,Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Toast.makeText(MainActivity.this,t.getMessage(),Toast.LENGTH_SHORT).show();
}
});
}
I want it to respond to some data.
Please help me. I got stuck into this from past 2 days.
Caused by: java.lang.IllegalArgumentException: URL
"notification/newnotification" does not contain "{userid}". (parameter #1)
means you should add the userId to the path like
public interface API {
#POST("notification/newnotification/{userid}")
Call<ResponseBody> getUserNotification(
#Path("userid") int userid
);
}
#Path("userid") maps the variable to the placeholder {userid}, that was missing.
I got it working by making some changes in API interface.
Below is new Code for API interface
#FormUrlEncoded
#POST("notification/newnotification")
Call<ResponseBody> getUserNotification(
#Field("userid") String userid // changed line
);

Get values with callback method for other class in android retrofit

I'm trying to get the data I parse from onResponse method via Callback. Here is my ApiClient:
public class ApiClient implements Callback<Map<String, Channel>> {
private ChannelCallback listener;
static final String BASE_URL = "https://www.radyoodtu.com.tr/";
public void start(ChannelCallback listener) {
Gson gson = new GsonBuilder()
.setLenient()
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
RestInterface restInterface = retrofit.create(RestInterface.class);
Call<Map<String, Channel>> call = restInterface.getChannels();
call.enqueue(this);
}
#Override
public void onResponse(retrofit2.Call<Map<String, Channel>> call, Response<Map<String, Channel>> response) {
System.out.println(response.code());
if(response.isSuccessful()) {
Map<String, Channel> body = response.body();
listener.setChannels(body);
List<Channel> channels = new ArrayList<>(body.values());
for (Channel channel : body.values()) {
System.out.println(channel.getSong());
}
}
}
#Override
public void onFailure(retrofit2.Call<Map<String, Channel>> call, Throwable t) {
//TODO
}
}
and this is the class I'm trying to get the data:
public class Radio implements ChannelCallback {
private ApiClient apiClient = new ApiClient();
public Radio(){
apiClient.start(this);
}
#Override
public void setChannels(Map<String, Channel> body) {
this.apiClient.onResponse(body); // NOT WORKING
}
}
here is my Interface:
public interface ChannelCallback {
void setChannels(Map<String, Channel> body);
}
what I need to do is get the onResponse body data for Radio class I'm using right now. In Radio class I have to create a List of channel objects with that data I need but I can't even get the data so I can't even create that list. I don't know how to manipulate the data from listener at all and I don't know how can I access that listener I use in ApiClient in Radio class.
It looks like you've got a cyclic reference here. Radio calls ApiClient start, which triggers the network request, which calls Radio.setChannels, which tries to call the client again.
I think you need to resolve two things:
Avoid this cyclic reference
You pass the listener to ApiClient.start() but you never assign it to the actual value inside ApiClient. So, my guess is that you get an NPE here if you have a successful response.
//i think no need to impliments ChannelCallback if this code works
//just asign your interface and apiclient in class
public class Radio implements ChannelCallback {
private ApiClient apiClient = new ApiClient();
private ChannelCallback channelCallback;
and in inside radio()
public Radio(){
apiClient.start(this);
channelCallback = apiClient.onResponse(body).create(ChannelCallback.class);
channelCallback.setChannels(Map<String, Channel> body)
}
//and recieve callback
}

Retrofit and Rxjava "Unable to create converter for java.util.List<Model>"

Have been having issue using Rxjava with Retrofit in my android app, everything seems ok and fine in the code implementation but app crashes whenever i navigate to the activity/fragment with the error message below.
//Error message
java.lang.IllegalArgumentException: Unable to create converter for java.util.List<com.thebestprice.bestprice.model.SearchRequestModel>
for method DataEndpointService.getStarredRepositories
//Endpoint Declaration
#GET("users/{user}/starred")
Observable<List<SearchRequestModel>> getStarredRepositories(#Path("user") String username);
//Client Class
public class DataClient {
private static final String PROJECT_BASE_URL = "https://api.github.com/";
private static DataClient instance;
private DataEndpointService queryResultService;
private DataClient(){
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
final Retrofit retrofit = new Retrofit.Builder().baseUrl(PROJECT_BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
queryResultService = retrofit.create(DataEndpointService.class);
}
public static DataClient getInstance(){
if (instance == null){
instance = new DataClient();
}
return instance;
}
public io.reactivex.Observable<List<SearchRequestModel>> queryForUserRepo(#NonNull String searchRequestModel){
return queryResultService.getStarredRepositories(searchRequestModel);
}
}
//Fragment to display the list
private void queryResultForSearchData(String userName){
disposable = DataClient.getInstance().
queryForUserRepo(userName).
subscribeOn(Schedulers.io()).
observeOn(AndroidSchedulers.mainThread()).
subscribe(new Consumer<List<SearchRequestModel>>() {
#Override
public void accept(List<SearchRequestModel> searchRequestModels) throws Exception {
mShimmerFrameLayout.stopShimmerAnimation();
rvAllSearch.setAdapter(new ResultAdapter(getActivity(), searchRequestModels));
}
},
new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) throws Exception {
}`enter code here`
});
}
//gradle dependencies for rxjava and retrofit with compileSdk27
//For using RxJava
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
implementation 'io.reactivex.rxjava2:rxjava:2.1.12'
//logging interceptor
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.1'
//For Using retrofit to do network request
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
Don't know what i'm doing wrong, have search for similar issues but doesn't seems to help in my own case
Main point of using RxJava it's avoid loops and list, to invoke Subscriptions and map functions, cause Observables managed all items. So you don't neet to return List.
Just one of example of using Github API with Rx.
public interface GithubService {
String SERVICE_ENDPOINT = "https://api.github.com";
#GET("/users/{login}")
Observable<Github> getUserRx(#Path("login") String login);
#GET("/users/{login}")
Github getUser(#Path("login") String login);
}
.
public class ServiceFactory {
/**
* Creates a retrofit service from an arbitrary class (clazz)
* #param clazz Java interface of the retrofit service
* #param endPoint REST endpoint url
* #return retrofit service with defined endpoint
*/
public static <T> T createRetrofitService(final Class<T> tClass, final String endPoint) {
final RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(endPoint)
.build();
T service = restAdapter.create(tClass);
return service;
}
}
.
// .....
service = ServiceFactory.createRetrofitService(
GithubService.class, GithubService.SERVICE_ENDPOINT);
service.getUserRx(login)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.cache()
.subscribe(new Subscriber<Github>() {
#Override
public final void onCompleted() {
}
#Override
public final void onError(Throwable e) {
Log.e(LOG, " ErrorRx Default Github" + e.getMessage());
}
#Override
public final void onNext(Github response) {
mCardAdapter.addData(response);
}
});
// .....
As you add GsonConverterFactory.
Check out the Bean you use (SearchRequestModel) the variable or the #SerializedName(alternate) annotation does not have the same variable name.
it work for me

Returning values from Service asynchronous method to Activity

I have a Service class that I am using to make web service calls using Volley:
public class AccountService {
public static void forgotPassword(Context c, String emailAddress) {
String url = "myUrl";
JsonArrayRequest request = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
// done
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
Volley.newRequestQueue(c).add(request);
}
}
And I'm calling it from an Activity like this:
public class ForgotPasswordActivity extends AppCompatActivity implements View.OnClickListener{
private void submit() {
accountService.forgotPassword();
}
}
When the Volley request is finished, I want to update the UI in my activity. How can I do this considering it is an asynchronous request? Am I able to call a method from the AccountService class in my activity? Thanks for the help
Pass a listener object to the AccountService and then send communication success or error to the activity.
Try as per below (you should not pass the layout to the AccountService which will create some unnecessary issues)
public class ForgotPasswordActivity extends AppCompatActivity
implements View.OnClickListener,
AccountServiceCallback{
private void submit() {
AccountService.forgotPassword("email#123.com", this);
}
#Override
public void onClick(View v) {
}
#Override
public void onResponse(JSONArray response) {
// UPDATE UI as per on response requirement
}
#Override
public void onErrorResponse(VollyError error) {
// UPDATE UI as per response flow
}
}
public class AccountService {
public static void forgotPassword(Context c, String email, final
AccountServiceCallback callback) {
String url = "myUrl";
JsonArrayRequest request = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
// done
callback.onResponse(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
callback.onErrorResponse(error);
}
});
Volley.newRequestQueue(c).add(request);
}
interface AccountServiceCallback {
public void onResponse(JSONArray response);
public void onErrorResponse(VollyError error);
}
}
You will have to find a way to get the result of your background work back onto the main thread so it can make changes to the view hierarchy. There are a LOT of ways to do this, and most of them are not really good.
But before you even do that, there are problems with your code. First, if you are thinking you made an Android Service component, you didn't actually do that. You made a class with the name AccountService, which does nothing special in the Android world.
Second, your call of forgotPassword() passes no arguments, but your definition of forgotPassword() in AccountService has a completely different signature. This wouldn't compile.
You should probably start learning about Android-specific asynchronous programming patterns and develop a strategy for solving your problem before writing code, because you'll almost certainly do it wrong without understanding what you're doing first.

Categories

Resources