Issue
I'm trying to update the recyclerview
Items from the data in SQLite
database which in turn gets updated with data fetched from API from time to time.
I have a TabLayout
which contain three fragments
.
Now in one fragment, I show the games played by the users in form of a recyclerView
. Each item of the recyclerView
contains the User Name, his high score and the no. of other users who have beaten his high score.
Now in the fragment, I'm calling an API to update a database inside AsyncTask
then again using the same database in the RecyclerView
Adapter Class to retrieve data in another AsyncTask
. The AsyncTask
is called periodically using TimerTask
and Handler.
@TargetApi(Build.VERSION_CODES.CUPCAKE)
@RequiresApi(api = Build.VERSION_CODES.CUPCAKE)
public class PerformBackgroundTask extends AsyncTask<String, Void, String>{
@Override
protected String doInBackground(String... gameID) {
try{
SQLiteDatabase challengeDatabase = mContext.openOrCreateDatabase("Challenge", Context.MODE_PRIVATE, null);
challengeDatabase.execSQL("CREATE TABLE IF NOT EXISTS DISPLAY_MESSAGE (gameID VARCHAR, highestScorer VARCHAR, count INT)");
Cursor d = challengeDatabase.rawQuery("SELECT * FROM DISPLAY_MESSAGE WHERE gameID", null);
int gameCode = d.getColumnIndex("gameID");
int highestScorer = d.getColumnIndex("highestScorer");
int count = d.getColumnIndex("count");
d.moveToFirst();
while(d!=null&&d.getCount()>0){
if((d.getString(gameCode)).equals(gameID)){
int k = Integer.parseInt(d.getString(count));
if(k>0)
{
return d.getString(highestScorer) + " and " + k + " others have beaten your highscore.";
}else if(k==0){
return d.getString(highestScorer) + " has beaten your highscore.";
}
else{
return "Yay! you have beaten all your opponents!";
}
}
d.moveToNext();
}
challengeDatabase.close();
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
public GridAdapterChallenge(Context c, List<CardContainer> listCards, Vector<Object> cardDetails, String sname) {
//selectedCards = new HashSet<Integer>();
inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mContext = c;
this.listCards = listCards;
this.sname = sname;
cards = cardDetails;
//notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private int viewType;
private ImageView imageView;
private Button increaseScore, challengeFriend;
private TextView challengeDetails, points, name, challengeCode;
private ImageView nativeAdIcon;
private TextView nativeAdTitle;
private TextView nativeAdBody;
private MediaView nativeAdMedia;
private TextView nativeAdSocialContext;
private Button nativeAdCallToAction;
private ProgressBar detailProgress;
public ViewHolder(@NonNull View itemView, int viewType) {
super(itemView);
view = itemView;
this.viewType = viewType;
if (viewType == 1) {
this.imageView = (ImageView) itemView.findViewById(R.id.thumb);
this.name = (TextView) itemView.findViewById(R.id.gameName);
this.challengeCode = itemView.findViewById(R.id.challengeCode);
this.points = itemView.findViewById(R.id.points);
this.challengeDetails = itemView.findViewById(R.id.challengeDetail);
this.increaseScore = itemView.findViewById(R.id.increaseScore);
this.challengeFriend = itemView.findViewById(R.id.challengeFriend);
this.challengeDetails = itemView.findViewById(R.id.challengeDetail);
this.detailProgress = itemView.findViewById(R.id.detailProgressBar);
} else {
this.nativeAdIcon = (ImageView) itemView.findViewById(R.id.native_ad_icon);
this.nativeAdTitle = (TextView) itemView.findViewById(R.id.native_ad_title);
this.nativeAdBody = (TextView) itemView.findViewById(R.id.native_ad_body);
this.nativeAdMedia = (MediaView) itemView.findViewById(R.id.native_ad_media);
this.nativeAdSocialContext = (TextView) itemView.findViewById(R.id.native_ad_social_context);
this.nativeAdCallToAction = (Button) itemView.findViewById(R.id.native_ad_call_to_action);
}
}
}
public void updateDetails(final TextView challengeDetails, final String gameId) {
final Handler handler;
handler = new Handler();
Timer timer = new Timer();
doAsynchronousTask = new TimerTask() {
@Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
PerformBackgroundTask performBackgroundTask = new PerformBackgroundTask();
challengeDetails.setText((CharSequence) performBackgroundTask.execute(gameId));
} catch (Exception e) {
}
}
});
}
};
timer.schedule(doAsynchronousTask, 4000, 5000); //execute in every 1000 ms
}
@Override
public void onBindViewHolder(@NonNull final ViewHolder viewHolder, final int i) {
if (viewHolder.viewType == 0) {
if (adList != null && adList.size() > (i+1)/5 - 1 && adList.get((i+1)/5 - 1) != null) {
NativeAd ad = adList.get((i+1)/5 - 1);
viewHolder.nativeAdSocialContext.setText(ad.getAdSocialContext());
viewHolder.nativeAdCallToAction.setText(ad.getAdCallToAction());
viewHolder.nativeAdCallToAction.setVisibility(View.VISIBLE);
viewHolder.nativeAdTitle.setText(ad.getAdHeadline());
viewHolder.nativeAdBody.setText(ad.getAdBodyText());
ad.registerViewForInteraction(viewHolder.itemView, viewHolder.nativeAdMedia, viewHolder.nativeAdIcon, Arrays.asList(viewHolder.nativeAdCallToAction, viewHolder.nativeAdMedia));
NativeAd.Image adCoverImage = ad.getAdCoverImage();
int bannerWidth = adCoverImage.getWidth();
int bannerHeight = adCoverImage.getHeight();
DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
int mediaWidth = viewHolder.itemView.getWidth() > 0 ? viewHolder.itemView.getWidth() : metrics.widthPixels;
viewHolder.nativeAdMedia.setLayoutParams(new LinearLayout.LayoutParams(mediaWidth, Math.min(
(int) (((double) mediaWidth / (double) bannerWidth) * bannerHeight), metrics.heightPixels / 3)));
ad.registerViewForInteraction(viewHolder.itemView, viewHolder.nativeAdMedia, Arrays.asList(viewHolder.nativeAdCallToAction, viewHolder.nativeAdMedia));
ad.registerViewForInteraction(viewHolder.itemView, viewHolder.nativeAdMedia);
}
} else{
viewHolder.name.setText(((CardContainer)cards.get(i)).name);
challengeCode = getChallengeCode(i);
viewHolder.challengeCode.setText(challengeCode);
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) mContext).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
if(getHighScore(((CardContainer)cards.get(i)).gameId)>0){
PerformBackgroundTask performBackgroundTask = new PerformBackgroundTask();
viewHolder.challengeDetails.setText(performBackgroundTask.execute(gameId).toString());
//updateDetails(viewHolder.challengeDetails, ((CardContainer)cards.get(i)).gameId);
}
else{
viewHolder.challengeDetails.setText("Press Increase Score To Play the Game");
}
viewHolder.detailProgress.setVisibility(View.GONE);
int width = displayMetrics.widthPixels;
try {
final String uri = ((CardContainer) cards.get(i)).imageurl;
if (uri != null) {
Picasso.get().load(uri)
.placeholder(R.mipmap.place)
.error(R.mipmap.place)
.resize(width / 2, width / 2)
.centerCrop()
.into(viewHolder.imageView);
}
}
catch (Exception e){
final String uri = null;
}
viewHolder.points.setText(String.valueOf(getHighScore(((CardContainer)cards.get(i)).gameId)));
viewHolder.increaseScore.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if (((CardContainer) cards.get(i)).link.contains("play.google.com")) {
openAppRating(mContext,((CardContainer) cards.get(i)).link.split("id=", 2)[1]);
}
else{
name = ((CardContainer) cards.get(i)).name;
link = ((CardContainer) cards.get(i)).link;
imageurl = ((CardContainer) cards.get(i)).imageurl;
type = ((CardContainer) cards.get(i)).type;
packageName = ((CardContainer) cards.get(i)).packageName;
gameId = ((CardContainer)cards.get(i)).gameId;
challengeNames.add(name);
updateDatabase(name, gameId, Config.uid+"@"+gameId, 0, viewHolder.points);
//String gameName, String gameId, String mychCode, int myHighScore
}
}
});
viewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
String name = ((CardContainer) cards.get(i)).name;
String link = ((CardContainer) cards.get(i)).link;
String imageurl = ((CardContainer) cards.get(i)).imageurl;
String type = ((CardContainer) cards.get(i)).type;
String packageName = ((CardContainer) cards.get(i)).packageName;
Bitmap bitmap = null;
Integer xyz = android.os.Build.VERSION.SDK_INT;
@Override
public boolean onLongClick(View view) {
bitmap = ((BitmapDrawable) viewHolder.imageView.getDrawable()).getBitmap();
if (sname.equals("fav")) {
// Toast.makeText(mContext, "in fav", Toast.LENGTH_SHORT).show();
final Dialog dialog = new Dialog(mContext);
dialog.setContentView(R.layout.custom_dialog);
TextView dialogText=dialog.findViewById(R.id.txt_dia);
dialogText.setText("Do you want to remove "+name+" from your favorites?");
dialog.show();
Button yes_button = (Button) dialog.findViewById(R.id.btn_yes);
yes_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
favf = new FavFunction(mContext);
int resultFav=favf.removeFromFavorite(link);
if (resultFav>=0){
cards.remove(resultFav);
notifyDataSetChanged();
}
dialog.dismiss();
}
});
Button no_button = (Button) dialog.findViewById(R.id.btn_no);
no_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
return true;
}
else{
final Dialog dialog = new Dialog(mContext);
dialog.setContentView(R.layout.custom_dialog);
TextView dialogText=dialog.findViewById(R.id.txt_dia);
dialogText.setText("Adding "+name+" to favorites... Do you also want to create it's homescreen shortcut?");
dialog.show();
Button yes_button = (Button) dialog.findViewById(R.id.btn_yes);
yes_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
favf = new FavFunction(mContext);
Boolean favstatus=favf.addToFavorite(imageurl, link ,name,type,packageName);
favf.addShortcut(name, link , imageurl,type,packageName,bitmap);
if(favstatus){
((Activity) mContext).recreate();
}
dialog.dismiss();
}
});
Button no_button = (Button) dialog.findViewById(R.id.btn_no);
no_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
favf = new FavFunction(mContext);
Boolean favstatus=favf.addToFavorite(imageurl, link, name,type,packageName);
if(favstatus){
((Activity) mContext).recreate();
}
dialog.dismiss();
}
});
return true;
}
}
});
viewHolder.challengeFriend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "Hey! I challenge you to beat my highscore " + getHighScore(gameId) + " in this awesome game. Enter my challenge code " + challengeCode + " in the \"Challenges\" Tab of 101 Game Store App. You can download the app from bit.ly/101gamestore");
sendIntent.setType("text/plain");
mContext.startActivity(sendIntent);
}
});
}
}
I want to update the no. of high scorer inside each item of the recyclerView
. However what is happening is the UI get frozen as soon as the TimerTask
starts. The data is being fetched successfully. Any solution approach better than mine would be appreciated.
Solution
For update your adapter, you should do it in main thread. AsyncTask provides onPostExecute method.
Do not replace adapter, instead you should replace data in the adapter.
class MyAsyncTask extends AsyncTask<Void, Void, List<String>> {
MyAdapter myAdapter;
ArrayList<String> values = new ArrayList<>();
public MyAsyncTask(MyAdapter adapter) {
this.myAdapter = myAdapter;
}
@Override
protected List<String> doInBackground(String... params) {
ArrayList<String> result = new ArrayList<>();
// long operation, for example: get results from url
return result;
}
@Override
protected void onPostExecute(List<String> list) {
myAdapter.setNewList(list);
}
}
class MyAdapter {
private List<String> list;
............
void setNewList(List<String> list) {
this.list = list;
notifyDataSetChanged();
}
............
}
Answered By - Алексей Мальченко
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.