What I am trying to do is, fetch the datas from server using GET method and display them in multiple textfields.
I have already made model class, interface and created constructor, but still the app throws onFailure message.
TextView name;
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
String url="https://jsonplaceholder.typicode.com/";
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
name = view.findViewById(R.id.proName);
name.setText("");
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
PlaceHolderApi placeHolderApi = retrofit.create(PlaceHolderApi.class);
Call<List<profileDetails>> call = placeHolderApi.getDetails();
call.enqueue(new Callback<List<profileDetails>>() {
#Override
public void onResponse(Call<List<profileDetails>> call, Response<List<profileDetails>> response) {
List<profileDetails> data=response.body();
**for (int i=0; i<data.size();i++)
name.append("Aa"+ data.get(i).getTitle());**
}
#Override
public void onFailure(Call<List<profileDetails>> call, Throwable t) {
Toast.makeText(getContext(),"nah it",Toast.LENGTH_LONG).show();
}
});
}
}
The result you are getting is a json object so try to create a model class having a data member of type List and making a call of type List make a call of that model type. This may resolve your issue.
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 1 year ago.
I am trying to implement "Retry" mechanism while using pagination library android, in case of no internet or device went offline while loading items.
When I click the "retry" image I get error - "Attempt to invoke virtual method 'void com.myapp.myapp.repository.FeedDataSource.retryPagination()' on a null object reference"
FeedDataSource.java
public class FeedDataSource extends PageKeyedDataSource<Long, Feed> {
.....
//for retry
private LoadParams<Long> params;
private LoadCallback<Long, Feed> callback;
........
#Override
public void loadAfter(#NonNull LoadParams<Long> params, #NonNull LoadCallback<Long, Feed> callback) {
this.params = params;
this.callback = callback;
Log.e(TAG, "Loading rage" + params.key + " Count" + params.requestedLoadSize);
networkState.postValue(NetworkState.LOADING);
RestApi restApi = RetrofitApi.create();
Call<FeedResponse> call = restApi.fetchFeed(params.key, params.requestedLoadSize, username);
try
{
Response<FeedResponse> response = call.execute();
if(response.isSuccessful()){
FeedResponse feedResponse = response.body();
if(feedResponse !=null){
networkState.postValue(NetworkState.LOADED);
List<Feed> responseItems = feedResponse.getFeeds();
callback.onResult(responseItems, params.key + 1);
}
}
........
}
public void retryPagination()
{
loadAfter(params, callback);
}
}
FeedDataFactory.java
public class FeedDataFactory extends DataSource.Factory {
private MutableLiveData<FeedDataSource> mutableLiveData;
private FeedDataSource feedDataSource;
private AppController appController;
public FeedDataFactory(AppController appController){
this.appController = appController;
this.mutableLiveData = new MutableLiveData<FeedDataSource>();
}
#Override
public DataSource create() {
feedDataSource = new FeedDataSource(appController);
mutableLiveData.postValue(feedDataSource);
return feedDataSource;
}
public MutableLiveData<FeedDataSource> getMutableLiveData(){
return mutableLiveData;
}
}
FeedViewModel.java
public class FeedViewModel extends ViewModel {
..............
public void retry() {
FeedDataFactory feedDataFactory = new FeedDataFactory(appController);
feedDataFactory.getMutableLiveData().getValue().retryPagination();
}
FeedAdapter.java
public class FeedListAdapter extends PagedListAdapter<Feed, RecyclerView.ViewHolder> {
......
private final Callback callback;
public FeedListAdapter(#NonNull DiffUtil.ItemCallback<Feed> diffCallback, Callback callback, Context context) {
super(Feed.DIFF_CALLBACK);
this.context = context;
this.callback = callback;
}
public void bindView(NetworkState networkState) {
if (networkState != null && networkState.getStatus() == NetworkState.Status.FAILED) {
binding.refresh.setVisibility(View.VISIBLE);
binding.refresh.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
binding.refresh.setVisibility(View.GONE);
binding.progressBar.setVisibility(View.VISIBLE);
callback.onRetryClicked();
}
});
}
}
public interface Callback {
void onRetryClicked();
}
}
HomeFragment.java
public class HomeFragment extends Fragment implements ClickHandler, FeedListAdapter.Callback {
private FeedListAdapter feedListAdapter;
private FeedViewModel feedViewModel;
..............
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
feedViewModel = new ViewModelProvider(this).get(FeedViewModel.class);
feedViewModel.init(appController);
feedListAdapter = new FeedListAdapter(Feed.DIFF_CALLBACK, this, getContext());
recyclerView.setAdapter(feedListAdapter);
feedViewModel.getArticleLiveData().observe(getViewLifecycleOwner(), pagedList -> {
feedListAdapter.submitList(pagedList);
});
}
}
Please help, what am I doing wrong!
First of all, I want to thank you because your solution is a hint for me to implement the network retry thing, I really appreciate that.
Second, about the NullPointerException you're getting, it's because in your FeedViewModel.java, when the retry button is triggered, you create a whole new factory for datasource. It's not either necessary or right because the Factory wont create any new DataSource unless the previous one was invalidated. You should retrieve the DataSource through your current Factory.
Another problem I want to mention is that, if your request is failed, you don't call onResult(...) on the callback. Based on the documentation:
A callback can be called only once, and will throw if called again. It
is always valid for a DataSource loading method that takes a callback
to stash the callback and call it later. This enables DataSources to
be fully asynchronous, and to handle temporary, recoverable error
states (such as a network error that can be retried)
Here is my implementation in DataSource when onFailure() in Retrofit is called:
#Override
public void onFailure(Call<HotItemsResponse> call, Throwable t) {
loadingState.postValue(Contants.LoadingState.SUB_LOAD_ERROR);
//when the load is fail, dont call onResult() on the call back,
//just ignore it, update the loading state for the UI to handle reload
//callback.onResult(new ArrayList<ProductItem>(), currentPage);
}
I want to get an ArrayList<ItemList> from my Retrofit Callback and save it in as a ArrayList variable in my class.
In other word I need to use data from retrofitList even when I leave the onResponse method.
What is the best way to do it?
Here is my code.
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
retrofitList = new ArrayList<>();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://b98afcf5.ngrok.io/")
.addConverterFactory(GsonConverterFactory.create())
.build();
jsonPlaceHolder = retrofit.create(JsonPlaceHolder.class);
Call<List<ItemList>> call = jsonPlaceHolder.getItemList();
call.enqueue(new Callback<List<ItemList>>() {
#Override
public void onResponse(Call<List<ItemList>> call, Response<List<ItemList>> response) {
if(!response.isSuccessful()) {
return;
}
List<ItemList> listOfitems = response.body();
for(ItemList itemList : listOfitems){
retrofitList.add(new ItemList(itemList.getId(),
itemList.getName(),
itemList.getPhone(),
itemList.getIsLocated()));
}
//I WANT TO SAVE "retrofitList" INTO MY CLASS FROM HERE
}
#Override
public void onFailure(Call<List<ItemList>> call, Throwable t) {}
});
}
I recommend serialization it will make your life easier. Try this and this.
Create a method in your class that you will call from onResponse with your list. Save the list in some field variable. If you call this variable before it is filled with items from onResponse it won't have them.
I have weather app, which is get weather information json from here:
http://icomms.ru/inf/meteo.php/?tid=44
There's a minus in "temp" value (for ex. : "temp":"−16"), and when I get value from json with retrofit2 and show it in textview it shows −16 instead of -16
How I can show -16 instead of −16?
Fragment from RecyclerViewAdapter (I use it to show weather info for multiply days), where I set text to textview
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
Meteo meteo = data.get(position);
holder.date.setText(meteo.date);
holder.tod.setText(meteo.tod);
holder.pressure.setText(meteo.pressure);
// THIS IS TEMPERATURE SETTING TEXT LINE
holder.temp.setText(meteo.temp);
holder.humidity.setText(meteo.humidity);
holder.wind.setText(meteo.wind);
holder.cloud.setText(meteo.cloud);
}
Weather data class:
public class Meteo {
public String date;
public String tod;
public String pressure;
public String temp;
public String humidity;
public String wind;
public String cloud;
}
Response body:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(APIService.HOST)
.addConverterFactory(GsonConverterFactory
.create())
.build();
APIService apiService = retrofit.create(APIService.class);
Call<List<Meteo>> call = apiService.getMeteo(44);
call.enqueue(new Callback<List<Meteo>>() {
#Override
public void onResponse(Call<List<Meteo>> call, Response<List<Meteo>> response) {
MeteoAdapter adapter = new MeteoAdapter(response.body());
// Method show just shows list of weather data
getViewState().show(adapter);
}
#Override
public void onFailure(Call<List<Meteo>> call, Throwable t) {
Log.d("MyLog", "WRONG");
}
});
Try this. I use it for formatting html tags in a textview:
String s = Html.fromHtml("−16");
tv.setText(s);
Reasoning: It sets the text as a Spanned object, rather than a string.
Note: Cannot test this currently, sorry if it doesnt work.
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
}
I have used "content" string to fetch the data from website and also in facebook integration to share the current page's data(content) on the wall, I attempted to add final in front of the declaration but that throws the following error within bundle... The final local variable connection cannot be assigned. It must be blank and not using a compound assignment.
How can i correct this?
private String headerContent;
public String html,content;
private Facebook mFacebook;
private AsyncFacebookRunner mAsyncRunner;
private Bundle bundle;
public String description,title;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.single_list_item);
facebook.setOnClickListener(new View.OnClickListener() {
//#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Bundle params = new Bundle();
mFacebook.dialog(Singlemenuitem.this, "feed",params,
(DialogListener) new SampleDialogListener());
}
});
if (bundle != null)
{
headerContent = bundle.getString("Header_Content");
content=bundle.getString("content");
url = bundle.getString("url");
webView.loadUrl(url);
}
}
You cannot make the variable final. final variables must be initialized either with an initializer expression or in the constructor(s). You are assigning to it in onCreate, which is too late in the lifecycle of the object.
Instead of making the variable public, make it private and provide an accessor method.
private String content;
public String getContent() {
return content;
}