Force retrofit to load new data - java

I'm using retrofit to get my json data in my recycleview. It used to work fine couple of weeks ago but I ran code now then It only loads data one time and then as many times as I make change any text or add new value in json data, It always load the same initial data on loading. I haven't used any cache property and strange thing is once it loads first time, then if i delete my json then still it loads the data instead of throwing exception and giving error of json not found.
What am I missing. I changed the version of retrofit but it dosesn't seem to work. Here is my code of Mainactivity is
GetDataService service = RetrofitClientInstance.getRetrofitInstance().create(GetDataService.class);
Call<List<RetroPhoto>> call = service.getAllPhotos();
call.enqueue(new Callback<List<RetroPhoto>>() {
#Override
public void onResponse(Call<List<RetroPhoto>> call, Response<List<RetroPhoto>> response) {
progressDoalog.dismiss();
generateDataList(response.body());
}
#Override
public void onFailure(Call<List<RetroPhoto>> call, Throwable t) {
progressDoalog.dismiss();
Toast.makeText(NewsActivity.this, "Something went wrong...Please try later!", Toast.LENGTH_SHORT).show();
}
});
}
/*Method to generate List of data using RecyclerView with custom adapter*/
private void generateDataList(List<RetroPhoto> photoList) {
recyclerView = findViewById(R.id.customRecyclerView);
adapter = new CustomAdapter(this,photoList);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(NewsActivity.this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
}
and code of GetDataService is
public interface GetDataService {
#GET("b.json")
Call<List<RetroPhoto>> getAllPhotos();
}
and my gradle is
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.okhttp:okhttp:2.4.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.7.0'
compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'
Thanks in advance for any help. I am banging my heads on floor over 3 hours on figuring out what excatly gone through in couple of weeks where I even didn't touch the code.

I realized problem was from server side as I was using ipage hosing, the i moved json to other hosing and immediately changes were shown in app on request but ipage didn't. So code is fine.

Related

Cancel adapter.notifyDataSetChanged

I'm kinda new to android and I wonder is it possible if after I've run notifyDataSetChanged(), I can cancel it in the middle.
For eg my case :
I would getPrice() then getTransaction if onResponse gets 1 as response.
I would set a swipeRefreshListener with the current code :
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
getTransactions(view);
Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new AccelerateInterpolator()); //and this
fadeIn.setDuration(1000);
swipeRefreshLayout.setRefreshing(true);
layoutBalance.setAnimation(fadeIn);
mActivities_RecyclerView.setAnimation(fadeIn);
swipeRefreshLayout.setRefreshing(false);
mActivities_RecyclerViewAdapter.notifyDataSetChanged();
}
});
I will recall getTransaction as I will need to get most updated data from the API.
But because my API call using retrofit enqueue will run async, my data would refresh first before I get the actual data from the server.
So, my question is that can I cancel notifyDataSetChanged() or do I need to change my implementation?
Assuming you've a Datamodel called as "APIData" and now you have once assigned it to the adapter and recyclerview,after the Swipereferesh happens and you have received the refreshed data,which would again be in a datamodel called as "APIData",now lets assume this to be APIData2,now just use
APIData.equals(APIData2)
this would check if the previous data is same to the new one,if its true you dont need to do notifyDataSetChanged()

How can i make parallel or concurent API calls?

I am building an Android app (my first app actually) and it's about getting similar tracks to the one you searched for. I am using retrofit2 with rxJava and gson for my calls.
For each track i found i add the corresponding image provided by the response in an imageview, but this image is not the actual album image, it's just an image of the band. I want to have the album image which i can get from the API if i do an album search.
So is there a way to make a API call that returns the album info for each track without losing to much time loading? I want these calls to happen in parallel with each other so as to be less visible to the "user" (me).
This is the code that i use to search for the similar tracks:
private void loadSimilarTracks() {
String mbid = selectedTrack.getMbid();
String artist = selectedTrack.getmArtist();
String track = selectedTrack.getName();
searchService = new LastFMSearchService();
Flowable<List<TrackSimilar>> fetchDataObservable = null;
if(!mbid.equals("")) {
fetchDataObservable = searchService.getSimilarTracks(mbid);
}
else{
fetchDataObservable = searchService.getSimilarTracks(artist, track);
}
mCompositeSubscription.add(fetchDataObservable
.timeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSubscriber<List<TrackSimilar>>() {
#Override
public void onNext(List<TrackSimilar> tracks) {
mTracks = tracks;
similarTrackAdapter.setTrackList(tracks);
}
#Override
public void onError(Throwable e) {
Toast.makeText(getActivity(), "API CALL ERROR", Toast.LENGTH_SHORT).show();
}
#Override
public void onComplete() {
resultsView.setVisibility(View.VISIBLE);
}
})
);
}
P.S i am using the lastFM api for my info.
Thanks in advance for any response.
Your code is good, one thing that you can do is that you can segment your code into multiple functions instead of a single one and run them as separate threads.
One function that makes api calls to search for similar tracks and other to get the image and trust me that significantly improves the response. Hope it helps..

Google Fit Listen for Data Updates not working

I'm trying to implement a Google Fit Listener when data is updated into Google Fit services.
In this link of Google Fit documentation there is a simple example, however, it is not 100% clear. For that reason, I have two problems:
I don't know how to implement mResultCallback variable (there aren't any examples in this documentation).
When I define a simple ResultCallback (it seems to work but I'm not sure) and I launch the application, it gives me a result error code: java.lang.SecurityException: Signature check failed
The code within the HistortyApi lists one of android.permission.ACCESS_FINE_LOCATION or android.permission.BODY_SENSORS as being required.
Adding those permissions to my code hasn't resolved the same problem though.
Confirmed bug in Google Fit services. See discussion in https://plus.google.com/110141422948118561903/posts/Lqri4LVR7cD
mResultCallback is a ResultCallback<Status> so you need to implement a class of that type. Documentation is here, but there's only one method you need to implement:
public abstract void onResult (Status result)
The standard way is to do this using an anonymous class either when you declare mResultCallback or when you're using it as a parameter. Below is an example from Google's BasicRecordingAPI example:
Fitness.RecordingApi.subscribe(mClient, DataType.TYPE_ACTIVITY_SAMPLE)
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
if (status.isSuccess()) {
if (status.getStatusCode()
== FitnessStatusCodes.SUCCESS_ALREADY_SUBSCRIBED) {
Log.i(TAG, "Existing subscription for activity detected.");
} else {
Log.i(TAG, "Successfully subscribed!");
}
} else {
Log.i(TAG, "There was a problem subscribing.");
}
}
});
If you want to use a member variable you can simply make an assignment instead:
ResultCallback<Status> mResultCallback = new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
...
}
});
Of course you can define a non-anonymous class, but if you did that for every callback you had you would end up creating a LOT of classes.

Best method of implementing Picasso.Builder and onImageLoadFailed function

For the past few days I have been implementing Picasso in my Android project. Initial implementation was easy enough, but now I have run into an issue I cannot seem to resolve and have not found a clear answer to in either the Picasso documentation or other tuturials/stackoverflow questions.
My knowledge of java is sufficient, but Android and more advanced OOP concepts are quite new to me so please bear this in mind.
Initially I implemented Picasso like this in my RecyclerViewAdapter:
public void onBindViewHolder(MyViewHolder viewHolder, int i) {
Picasso.with(viewHolder.image.getContext()).setIndicatorsEnabled(true);
Picasso.with(viewHolder.image.getContext())
.load(new File("imagePath"))
.fit()
.centerCrop()
.into(viewHolder.image);
}
This worked fine, but due to unrelated errors I wished to implement debugging options and looked towards the onError() and onImageLoadFailed() functions. Resulting in the following implementation:
Picasso.Builder builder = new Picasso.Builder(viewHolder.image.getContext());
builder.indicatorsEnabled(true);
builder.loggingEnabled(true);
builder.listener(new Picasso.Listener() {
#Override
public void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception) {
Log.d("TAG", " onImageLoadFailed message");
exception.printStackTrace();
}
});
builder.build().load(new File("imagePath"))
.fit()
.centerCrop()
.into(viewHolder.image, new com.squareup.picasso.Callback() {
#Override
public void onError() {
Log.d("TAG", " onError message");
}
});
However, with this implementation Picasso seemed to never reload images from memory when I scrolled through my Recyclerviewer. Therefore I tried the following:
Picasso picasso = new Picasso.Builder(viewHolder.image.getContext()).listener(new Picasso.Listener() {
#Override
public void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception) {
Log.d("TAG", " onImageLoadFailed message");
exception.printStackTrace();
}
}).build();
picasso.with(viewHolder.image.getContext())
.setIndicatorsEnabled(true);
picasso.with(viewHolder.image.getContext())
.load(new File("imagePath"))
.fit()
.centerCrop()
.into(viewHolder.image, new com.squareup.picasso.Callback() {
#Override
public void onError() {
Log.d("TAG", " onError message");
}
});
This implementation seems to work nicely (although it does seem that some images are loaded in memory much quicker than others, perhaps due to .fit(), my next objective will be to optimize file loading speed).
However I am uncertain if this is the best implementation. I have tried to find the answer in the Picasso documentation and it seems to be related to the creation of new Picasso instances / Picasso being a singelton. However, I am afraid I am too inexperienced to fully understand this and there seem to be no tutorials on this topic.
So my main question is as follows: What is the best way of implementing Picasso in a project/throughout multiple activities? Should I use Picasso.Builder to access the onImageLoadFailed function? And if so, should I use it for every activity or not?
Thank you in advance for your help!

How can these two json be different?

I am using volley with android. As I am studying this example on github https://github.com/evancharlton/folly . That project made a perfect solution of querying json.
Now comes the problem. If I replace the json url there with another, then the fetching seems not to work!
I know different jsonws need different parsing jobs so I extremely simplified the code. Like this.
public class MainActivity extends SherlockFragmentActivity {
/**
* Called when the activity is first created.
*/
private ViewPager pager;
private PagerSlidingTabStrip tabs;
private MyPagerAdapter adapter;
private String url = "http://konachan.com/post.json?limit=1";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final TextView txt = (TextView) findViewById(R.id.text);
txt.setText("initial");
RequestQueue queue = Volley.newRequestQueue(this);
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
public void onResponse(JSONObject response) {
txt.setText("somethinghappend");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
Log.e("wtf", error.toString()) ;
}
});
queue.add(jsObjRequest);
}
}
As you can tell, I removed everything about the content of json but only doing this to figure out why the code goes wrong with only one change: the url
To make it clear:(i dont have enough reputation for multi links so use the comment insdead)
when I set url to
(comment 1)
my TextView successfully change his text(this is the json used in the example project from github, though this is meaningless information since I had built very unrelated code from the example)
but when I switch the address to
(comment 2)
nothing happen to my TextView!(this is the json I really need to work with)
And yes, both jsons are correctly fetched and parsed and displayed in firefox(without any kind of proxy), so I think there are nothing wrong with the jsons and the network.
In fact I think the ONLY difference is that they are different jsons.... with 2 different urls....
Now I seek help from you guys, how can that be? Nothing changed but only a smaller json.. makes everything broken? (is it about timeout matters? but both are loaded very fast in firefox... and obviously the working one contains much more bytes than the not working one...)
the error logged 410 error. The page has Gone?! But it is alive in firefox... and the other json works in both environment(firefox and app)

Categories