I am trying to get values from a web using retrofit and rxAndroid but onNext doesn't called.
Here, my classes:
public class ForumService {
private static final String FORUM_SERVER_URL = "http://192.168.1.104:8080/curso-fullstack/symfony/web";
private ForumApi mForumApi;
public ForumService(){
RequestInterceptor requestInterceptor = new RequestInterceptor() {
#Override
public void intercept(RequestFacade request) {
request.addHeader("Accept", "application/json");
}
};
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(FORUM_SERVER_URL)
.setRequestInterceptor(requestInterceptor)
.setLogLevel(RestAdapter.LogLevel.FULL)
.build();
mForumApi = restAdapter.create(ForumApi.class);
}
public ForumApi getmForumApi() {
return mForumApi;
}
public interface ForumApi{
#GET("/video/lasts_videos")
public Observable<List<Data>> getVideos();
/*#GET("/posts/{id}")
public Observable<Post>
getPost(#Path("id") int postId);
#GET("/comments")
public Observable<List<Comment>>
getComments(#Query("postId") int postId);
#POST("/posts")
public Observable<Post> postPost(Post post);*/
}
}
public class ListPresenter {
ListActivity mView;
ForumService mForum;
public ListPresenter(ListActivity mView, ForumService mForum) {
this.mView = mView;
this.mForum = mForum;
}
public void loadPosts() {
mForum.getmForumApi()
.getVideos()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<Data>>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(List<Data> posts) {
mView.displayPosts(posts);
}
});
}
}
And then, I execute the method loadPosts() from my activity, to fill a list and display in a ListView.
If i look about android logs, I can see how retrofit displays to me that found the results, but for any reason onNext is never called.
From the discussion in the comments:
onNext wan't been called because there was a problem in the JSON deserialization. onError was called instead.
Related
. Get stuck with a basic scenario of loading the data in oncreate of an activity. So I am trying to load the data as soon as i open my activity but when i change the screen orientation it gets called again.
below is my rest client for retrofit
public class MyRestApiClient {
private static Retrofit retrofit = null;
public static Retrofit getClient() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).connectTimeout(30,TimeUnit.SECONDS).readTimeout(30,TimeUnit.SECONDS).build();
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
retrofit = new Retrofit.Builder()
.baseUrl("http://localhost:8080/rest/")
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(client)
.build();
return retrofit;
}
}
below is my resturl interface for loading the data
public interface MyRestUrlInterface {
#GET("user/{user_id}")
Call<Object> getData(#Path("user_id") String user_id);
}
below is my viewmodel class:
public class MyViewModelObserver extends ViewModel {
private MutableLiveData<Object> httpCallBackObserver;
public MutableLiveData<Object> getHttpCallBackObserver() {
if (httpCallBackObserver == null) {
httpCallBackObserver = new MutableLiveData<Object>();
}
return httpCallBackObserver;
}
}
below is my Activity code :
public class MyActivity extends AppCompatActivity {
private static final String TAG = "MyActivity" ;
MyRestUrlInterface restUrlInterface;
public MyViewModelObserver myViewModelObserver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
restUrlInterface = MyRestApiClient.getClient().create(MyRestUrlInterface.class);
myViewModelObserver = ViewModelProviders.of(this).get(MyViewModelObserver.class);
myViewModelObserver.getHttpCallBackObserver().observe(this, getData());
//load data via http
Call<Object> call = restUrlInterface.getData("123");
call.enqueue(new Callback<Object>() {
#Override
public void onResponse(Call<Object> call, Response<Object> response) {
myViewModelObserver.getHttpCallBackObserver().setValue(response.body());
}
#Override
public void onFailure(Call<Object> call, Throwable t) {
}
});
}
private Observer<Object> getData(){
return new Observer<Object>() {
#Override
public void onChanged(#Nullable final Object responseString) {
Log.d(TAG,"***** Loaded Data --- "+responseString);
}
};
}
}
How to use view model so that it wont make http call again in screen orientation change
suggested answer:
public class MyViewModelObserver extends ViewModel {
private MutableLiveData<Object> httpCallBackObserver;
public MutableLiveData<Object> getHttpCallBackObserver() {
if (httpCallBackObserver == null) {
httpCallBackObserver = new MutableLiveData<Object>();
loadData();
}
return httpCallBackObserver;
}
private void loadData(){
Call<Object> call = restUrlInterface.getData("123");
call.enqueue(new Callback<Object>() {
#Override
public void onResponse(Call<Object> call, Response<Object> response) {
myViewModelObserver.getHttpCallBackObserver().setValue(response.body());
}
#Override
public void onFailure(Call<Object> call, Throwable t) {
}
});
}
}
I have an API interface which has two overloaded methods:
public interface Api {
#GET("movie/now_playing")
Call<ApiResponse> getMovies(#Query("page") int page);
#GET("search/movie")
Call<ApiResponse> getMovies(#Query("query") String query, #Query("page") int page);
}
First one is used to get now playing movies and the second one to search for movies.
In my MainActivity I use this code to display the data in a RecyclerView:
MovieViewModel movieViewModel = ViewModelProviders.of(this).get(MovieViewModel.class);
MovieAdapter adapter = new MovieAdapter(this);
movieViewModel.moviePagedList.observe(this, adapter::submitList);
recyclerView.setAdapter(adapter);
This is my MovieViewModel class:
public class MovieViewModel extends ViewModel {
LiveData<PagedList<ApiResponse.Movie>> moviePagedList;
public MovieViewModel() {
MovieDataSourceFactory movieDataSourceFactory = new MovieDataSourceFactory();
PagedList.Config config = new PagedList.Config.Builder().setEnablePlaceholders(false).setPageSize(20).build();
moviePagedList = new LivePagedListBuilder<>(movieDataSourceFactory, config).build();
}
}
And this my MovieDataSourceFactory class:
public class MovieDataSourceFactory extends DataSource.Factory<Integer, ApiResponse.Movie> {
private MutableLiveData<PageKeyedDataSource<Integer, ApiResponse.Movie>> movieLiveDataSource = new MutableLiveData<>();
#Override
public DataSource<Integer, ApiResponse.Movie> create() {
MovieDataSource movieDataSource = new MovieDataSource();
movieLiveDataSource.postValue(movieDataSource);
return movieDataSource;
}
}
And this is my MovieDataSource class:
public class MovieDataSource extends PageKeyedDataSource<Integer, ApiResponse.Movie> {
#Override
public void loadInitial(#NonNull LoadInitialParams<Integer> params, #NonNull LoadInitialCallback<Integer, ApiResponse.Movie> callback) {
Api api = RetrofitClient.getInstance().getApi();
Callback<ApiResponse> call = new Callback<ApiResponse>() {
#Override
public void onResponse(#NonNull Call<ApiResponse> call, #NonNull Response<ApiResponse> response) {
if(response.body() != null){
callback.onResult(response.body().movieList, null, page + 1);
}
}
#Override
public void onFailure(#NonNull Call<ApiResponse> call, #NonNull Throwable t) {}
};
api.getMovies(page).enqueue(call);
}
//loadBefore and loadAfter methods
}
If I run this code, everything works fine, the first query is invoked and I get the result correctly. The question is, how can I dynamically use one or the other?
api.getMovies(query, page).enqueue(call);
boolean globalVariableShouldUseGetMoviesCallWithOnlyOneArgument = true
private void doNetworkCallAndCheckBooleanStatus(){
if (globalVariableShouldUseGetMoviesCallWithOnlyOneArgument) {
getMovies(thisIsOneArgumentAsYouCanSee);
} else {
getMovies(thisIsUsingTwoArguments, asYouCanSee);
}
}
private void someOtherMethodInTheApp() {
globalVariableShouldUseGetMoviesCallWithOnlyOneArgument = false
doNetworkCallAndCheckBooleanStatus()
}
I am implementing get request with Retrofit in Mvvm architecture, but call.enqueue is not getting executed. When i try it without mvvm architecture in simple activity it works fine.
Github:
https://github.com/nikolabozicbg/Retrofit
I tried to log onresponse and onfailure but nothing gets logged
Here is my Fragment code:
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
listItemViewModel = ViewModelProviders.of(this, viewModelFactory)
.get(ListGamesViewModel.class);
listItemViewModel.getListItems().observe(this, new Observer<List<ListGames>>() {
#Override
public void onChanged(#Nullable List<ListGames> listItems) {
}
});
}
View model code:
public class ListGamesViewModel extends ViewModel {
private RetrofitRpository repository;
public ListGamesViewModel(RetrofitRpository repository) {
this.repository = repository;
}
public LiveData<List<ListGames>> getListItems() {
System.out.println("iz live model");
return (LiveData<List<ListGames>>) repository.getListOfData();
}
}
Repository code:
public class RetrofitRpository {
List<ListGames> listItemList;
public RetrofitRpository() {
}
public List<ListGames> getListOfData() {
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("http://mobilews.365scores.com/").addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
LisgGamesCLient client = retrofit.create(LisgGamesCLient.class);
Call<Example> call = client.reposForUser();
call.enqueue(new Callback<Example>() {
#Override
public void onResponse(Call<Example> call, Response<Example> response) {
System.out.println("onresponse");
}
#Override
public void onFailure(Call<Example> call, Throwable t) {
System.out.println("onfail");
}
});
return listItemList;
}
}
CLient code:
public interface LisgGamesCLient {
#GET("Data/Games/?lang=1&uc=6&tz=15&countries=1")
Call<Example> reposForUser();
}
Example class code:
I am using retrofit2 with rxjava2.
I have used mostly the latest library in my gradle and I have tried many methods for creating adapter .
I have also created some custom adapter but nothing seems to work with it
service :
public static Retrofit getClient() {
if (retrofit==null) {
retrofit = new Retrofit.Builder().baseUrl(AppConstants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create()).
addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();
}
return retrofit;
}
fragment code:
ApiInterface apiInterface
=ApiClient.getClient().create(ApiInterface.class);
apiInterface.getCategoryVideos(AppConstants.API_KEY)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Observer<Video>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(Video value) {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
}
});
I have tried many adapters but no adapter is working . I am
the log output is :
Any suggestion or solution is appreciated .
I have also tried the solution in this link stackoverflow solution
Try to change create client
public class MyClient {
private static MyClient instance;
private ApiInterface apiInterface;
private MyClient() {
final Retrofit retrofit = new Retrofit.Builder().baseUrl(AppConstants.BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
gitHubService = retrofit.create(ApiInterface.class);
}
public static MyClient getInstance() {
if (instance == null) {
instance = new MyClient();
}
return instance;
}
}
and fragment code
private Subscription subscription;
...
subscription = MyClient.getInstance().getCategoryVideos(AppConstants.API_KEY)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Video>() {
#Override public void onCompleted() {
Log.d(TAG, "In onCompleted()");
}
#Override public void onError(Throwable e) {
e.printStackTrace();
Log.d(TAG, "In onError()");
}
#Override public void onNext(Video value) {
Log.d(TAG, "In onNext()");
}
});
How can I make the element in List<Contributor> of Observable<List<Contributor>> launch one by one like Observable<Contributor>.
"Contributor" is a custom class.
public class MainActivity extends AppCompatActivity {
private TextView mTv;
private interface GitHubService {
#GET("repos/{owner}/{repo}/contributors")
Observable<List<Contributor>> contributors(#Path("owner") String owner, #Path("repo") String repo);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTv= (TextView) findViewById(R.id.tv_content);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(new OkHttpClient())
.build();
GitHubService service=retrofit.create(GitHubService.class);
service.contributors("square","retrofit")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<List<Contributor>>() {
#Override
public void call(List<Contributor> contributors) {
//TODO
}
});
}
}
That is my code. I want get the result like this finally :
subscribe(new Action1<Contributor>() {
#Override
public void call(Contributor contributor) {
//TODO
}
});
You can apply flatMap to Observable<List<...>> and create new observable from List:
Observable.just(Arrays.asList("A", "B", "C"))
.flatMap(new Func1<List<String>, Observable<String>>() {
#Override
public Observable<String> call(List<String> list) {
return Observable.from(list);
}
})
.subscribe(new Action1<String>() {
#Override
public void call(String x) {
System.out.println(x);
}
});