I have implemented Admob in my app and working well with test ads.
I am loading ads in feed list, and getting error " Failed to load Ad: 0". According to Stack Overflow answers, this error mostly related to newly created ad units, but it had been more than 15 days but getting the same error. While rewarded video ad unit is working fine. Admob account is also with approved status. Asked the same question in Google Admob Community, but no answer.
Don't mark it duplicate of this question as the accepted answer says to wait, but in my case, I am waiting for last 15 days.
Here is code snippet.
private void showNativeGoogleAd(UnifiedNativeAdViewHolder holder)
{
AdLoader adLoader = new AdLoader.Builder(mContext, mContext.getString(R.string.admob_social_wall_ad_unit_id))
//AdLoader adLoader = new AdLoader.Builder(mContext, "ca-app-pub-3940256099942544/1044960115")
.forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
// Show the ad.
populateNativeAdView(unifiedNativeAd, holder.adView);
//holder.fl_adplaceholder.removeAllViews();
//holder.fl_adplaceholder.addView(holder.adView);
}
})
.withAdListener(new AdListener() {
#Override
public void onAdFailedToLoad(int errorCode) {
// Handle the failure by logging, altering the UI, and so on.
Log.d("TAG", "onAdFailedToLoad: Google => "+errorCode);
}
})
.withNativeAdOptions(new NativeAdOptions.Builder()
// Methods in the NativeAdOptions.Builder class can be
// used here to specify individual options settings.
.build())
.build();
adLoader.loadAd(new AdRequest.Builder().build());
}
private void populateNativeAdView(UnifiedNativeAd nativeAd,
UnifiedNativeAdView adView) {
// Some assets are guaranteed to be in every UnifiedNativeAd.
((TextView) adView.getHeadlineView()).setText(nativeAd.getHeadline());
((TextView) adView.getBodyView()).setText(nativeAd.getBody());
((Button) adView.getCallToActionView()).setText(nativeAd.getCallToAction());
// These assets aren't guaranteed to be in every UnifiedNativeAd, so it's important to
// check before trying to display them.
com.google.android.gms.ads.formats.NativeAd.Image icon = nativeAd.getIcon();
if (icon == null) {
adView.getIconView().setVisibility(View.INVISIBLE);
} else {
((ImageView) adView.getIconView()).setImageDrawable(icon.getDrawable());
adView.getIconView().setVisibility(View.VISIBLE);
}
if (nativeAd.getPrice() == null) {
adView.getPriceView().setVisibility(View.INVISIBLE);
} else {
adView.getPriceView().setVisibility(View.VISIBLE);
((TextView) adView.getPriceView()).setText(nativeAd.getPrice());
}
if (nativeAd.getStore() == null) {
adView.getStoreView().setVisibility(View.INVISIBLE);
} else {
adView.getStoreView().setVisibility(View.VISIBLE);
((TextView) adView.getStoreView()).setText(nativeAd.getStore());
}
if (nativeAd.getStarRating() == null) {
adView.getStarRatingView().setVisibility(View.INVISIBLE);
} else {
((RatingBar) adView.getStarRatingView())
.setRating(nativeAd.getStarRating().floatValue());
adView.getStarRatingView().setVisibility(View.VISIBLE);
}
if (nativeAd.getAdvertiser() == null) {
adView.getAdvertiserView().setVisibility(View.INVISIBLE);
} else {
((TextView) adView.getAdvertiserView()).setText(nativeAd.getAdvertiser());
adView.getAdvertiserView().setVisibility(View.VISIBLE);
}
// Assign native ad object to the native view.
adView.setNativeAd(nativeAd);
}
Related
I am integrating Unity Facebook SDK to a project, right now I am making a log-in system. I have written a script, attached it to an object on a scene, created a button, added the FbLogin method as a listener of OnClick UnityEvent of my button and built an app for Android. Also I have pasted all the needed keys and tokens.
using System.Collections.Generic;
using UnityEngine;
using Facebook.Unity;
class FacebookLoginSystem
{
private void Awake()
{
FB.Init(SetInit, OnHideUnity);
}
void SetInit()
{
if (FB.IsLoggedIn)
{
Debug.Log("Logged in Successfuly!");
}
else
{
Debug.Log("FB is not loggid in");
}
}
void OnHideUnity(bool isGameShown)
{
if (isGameShown)
{
Time.timeScale = 1;
}
else
{
Time.timeScale = 0;
}
}
public void FbLogin()
{
List<string> permessions = new List<string>();
permessions.Add("public_profile");
FB.LogInWithReadPermissions(permessions, AuthCallResult);
}
private void AuthCallResult(ILoginResult result)
{
if (result.Error != null)
{
Debug.Log(result.Error);
}
else
{
if (FB.IsLoggedIn)
{
Debug.Log("FB logged in");
Debug.Log(result.RawResult);
FB.API("/me?fields=first_name", HttpMethod.GET, callbackData);
}
else
{
Debug.Log("Login Failed!");
}
}
}
}
But when I press the button in my build, I get this. ("Something went wrong, we are working on it...")
Tell me, please, why does it happen?
This happens when I press the button
UPD:
I have replaced the methods FbLogin and AuthCallback with these versions. Also I added a serialized field TextForLogging to see my logs in Build, and it tells me that "User cancelled login".
public void FbLogin()
{
var perms = new List<string>() { "public_profile", "email" };
FB.LogInWithReadPermissions(perms, AuthCallback);
}
private void AuthCallback(ILoginResult result)
{
if (FB.IsLoggedIn)
{
// AccessToken class will have session details
var aToken = Facebook.Unity.AccessToken.CurrentAccessToken;
// Print current access token's User ID
Debug.Log(aToken.UserId);
TextForLogging.text += $"\n{aToken.UserId}";
// Print current access token's granted permissions
foreach (string perm in aToken.Permissions)
{
Debug.Log(perm);
TextForLogging.text += $"\n{perm}";
}
FB.API("/me?fields=first_name", HttpMethod.GET, callbackData);
}
else
{
Debug.Log("User cancelled login");
TextForLogging.text += "\nUser cancelled login";
}
}
I modified my project code to retrieve admob id from a server to show admob banner/interstitial using particular value of id by volley lib. Consequently, my application crashes each time the interstitial starts
The logcat points that "The ad unit ID must be set on InterstitialAd before loadAd is called."
This warning is caused by
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
if (!isRedirected || INCREMENT_WITH_REDIRECTS) {
super.onPageStarted(view, url, favicon);
webViewCount = webViewCount + 1;
if (webViewCount >= ServerClass.SHOW_AD_AFTER_X) {
if (ServerClass.SHOW_FULL_SCREEN_AD && !HIDE_ADS_FOR_PURCHASE) {
if (ServerClass.USE_FACEBOOK_ADS) {
if (facebookInterstitialAd != null) {
facebookInterstitialAd.loadAd();
}
} else {
if (mInterstitialAd != null) {
final AdRequest fullscAdRequest = new AdRequest.Builder().build();
mInterstitialAd.loadAd(fullscAdRequest);
}
}
}
}
}
}
So when I change it to
if (mInterstitialAd != null) {
final AdRequest fullscreenAdRequest = new AdRequest.Builder().build();
mInterstitialAd.setAdUnitId(ServerClass.interstitial_full);
mInterstitialAd.loadAd(fullscreenAdRequest);
}
I got another warning "The ad unit ID can only be set once on InterstitialAd."
since setAdUnitId is already used in an if statement in onCreate method:
if (!HIDE_PURCHASE) {
if (ServerClass.FACEBOOK_ADS) {
//CODE
} else {
mInterstitialAd = new InterstitialAd(this);
mInterstitialAd.setAdUnitId(ServerClass.interstitial_full);
mInterstitialAd.setAdListener(new AdListener() {
public void onAdLoaded() {
showInterstitial();
}
});
}
How could I prevent my app from crashing, and why is retrieving data from server would cause that though the data is already present based on Log msg
I am using admob for ads. Ads working very well on the Editor but on the phone it doesn't. I have a button in the game that show rewarded ads then load next level. And I am showing interstitial ads at end of the level then load next level. But after loading next level game crashes. I am trying to fix it for days but it keeps happening. I am adding my ad manager script. (unit ids not empty of course)
using System.Collections;
using UnityEngine;
using GoogleMobileAds.Api;
using System;
public class AdManager : MonoBehaviour
{
public static AdManager instance;
private BannerView bannerView;
private RewardedAd rewardedAd;
private InterstitialAd interstitialAd;
#if UNITY_ANDROID
string bannerAdUnitId = " ";
string rewardedAdUnitId = " ";
string interstitialAdUnitId = " ";
#else
string bannerAdUnitId = "unexpected_platform";
string rewardedAdUnitId = "unexpected_platform";
string interstitialAdUnitId = "unexpected_platform";
#endif
void Awake()
{
if(instance != null && instance != this){
Destroy(this.gameObject);
}
else{
instance = this;
DontDestroyOnLoad(this.gameObject);
}
}
private void Start() {
MobileAds.Initialize(initStatus => { });
RequestInterstitialAd();
RequestBannerAd();
RequestRewardedAd();
}
//BANNER
public void RequestBannerAd(){
if (bannerView != null)
bannerView.Destroy();
else{
bannerView = new BannerView(bannerAdUnitId, AdSize.Banner, AdPosition.Bottom);
AdRequest request = new AdRequest.Builder().Build();
bannerView.LoadAd(request);
}
}
//REWARDED
public void RequestRewardedAd(){
if(rewardedAd != null)
rewardedAd.Destroy();
rewardedAd = new RewardedAd(rewardedAdUnitId);
// Called when an ad request failed to show.
rewardedAd.OnAdFailedToShow += HandleRewardedAdFailedToShow;
// Called when the ad is closed.
rewardedAd.OnAdClosed += HandleRewardedAdClosed;
AdRequest request = new AdRequest.Builder().Build();
rewardedAd.LoadAd(request);
}
public void ShowRewardedAd(){
if (rewardedAd.IsLoaded()) {
rewardedAd.Show();
}
else{
StartCoroutine(RewardedNotLoadedFunctionCall());
}
}
IEnumerator RewardedNotLoadedFunctionCall(){
FindObjectOfType<GameManagement>().RewardedAdNotLoaded();
yield return null;
}
public void HandleRewardedAdClosed(object sender, EventArgs args)
{
RequestRewardedAd();
StartCoroutine(AdClosedFunctionCall());
}
IEnumerator AdClosedFunctionCall(){
FindObjectOfType<GameManagement>().AdClosed();
yield return null;
}
public void HandleRewardedAdFailedToShow(object sender, AdErrorEventArgs args)
{
StartCoroutine(RewardedNotLoadedFunctionCall());
}
//interstitial
private void RequestInterstitialAd(){
if(interstitialAd != null)
interstitialAd.Destroy();
interstitialAd = new InterstitialAd(interstitialAdUnitId);
interstitialAd.OnAdClosed += HandleOnAdClosed;
AdRequest request = new AdRequest.Builder().Build();
interstitialAd.LoadAd(request);
}
public void ShowInterstitialAd(){
if (interstitialAd.IsLoaded()) {
interstitialAd.Show();
}
else{
StartCoroutine(AdClosedFunctionCall());
}
}
public void HandleOnAdClosed(object sender, EventArgs args)
{
RequestInterstitialAd();
StartCoroutine(AdClosedFunctionCall());
}
}
logcat
Admob Ad does not run on the same thread as Unity's main thread.
rewardedAd.OnAdClosed += HandleRewardedAdClosed;
Calling Unity's function from Admob's thread will lead to unexpected error.
First, add UnityMainThreadDispatcher to your project. All functions called by Admob's callback need be queued by UnityMainThreadDispatcher to main thread:
public void HandleRewardedAdClosed(object sender, EventArgs args)
{
UnityMainThreadDispatcher.Instance().Enqueue(()=>{
RequestRewardedAd();
StartCoroutine(AdClosedFunctionCall());
});
}
Secondly, you should not use FindObjectOfType(). This is an expensive operation and you might run into NullReferenceException if it fails to find the GameManagement object. And since this exception did not happen on Unity's main thread, the logcat message was cryptic.
You should use Singleton or Observer pattern instead.
Thirdly, you're giving reward to user even if they skip the reward ad. Use rewardedAd.OnUserEarnedReward to make sure user have earned the reward ad.
I am building a real time multiplayer game using 'Google Play Games Services'. My question is that when peers are connected to a room and playing the game, and one of them puts their application in background that peer gets disconnected from room, and other peers receives callback of that peer leaving the room, is their a way to prevent this from happening.
For testing purpose fragment does not call to leave that room in any of its life cycle methods.
I've added code snippets to provide better understanding.
#Override
public void onStop() {
super.onStop();
// if (mRoomId!=null && !mRoomId.isEmpty()) {
// Games.RealTimeMultiplayer.leave(((MainActivity) getActivity()).getGoogleApiClient(), roomUpdateListener, mRoomId);
// }
// getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// mPlaying = false;
}
#Override
public void onActivityResult(int request, int response, Intent data) {
if (request == RC_SELECT_PLAYERS) {
if (response != Activity.RESULT_OK) {
// user canceled
return;
}
// get the invitee list
Bundle extras = data.getExtras();
final ArrayList<String> invitees =
data.getStringArrayListExtra(Games.EXTRA_PLAYER_IDS);
// get auto-match criteria
Bundle autoMatchCriteria = null;
int minAutoMatchPlayers =
data.getIntExtra(Multiplayer.EXTRA_MIN_AUTOMATCH_PLAYERS, 0);
int maxAutoMatchPlayers =
data.getIntExtra(Multiplayer.EXTRA_MAX_AUTOMATCH_PLAYERS, 0);
if (minAutoMatchPlayers > 0) {
autoMatchCriteria = RoomConfig.createAutoMatchCriteria(
minAutoMatchPlayers, maxAutoMatchPlayers, 0);
} else {
autoMatchCriteria = null;
}
// create the room and specify a variant if appropriate
RoomConfig.Builder roomConfigBuilder = makeBasicRoomConfigBuilder();
roomConfigBuilder.addPlayersToInvite(invitees);
if (autoMatchCriteria != null) {
roomConfigBuilder.setAutoMatchCriteria(autoMatchCriteria);
}
RoomConfig roomConfig = roomConfigBuilder.build();
Games.RealTimeMultiplayer.create(((MainActivity) getActivity()).getGoogleApiClient(), roomConfig);
// prevent screen from sleeping during handshake
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
if (request == RC_WAITING_ROOM) {
if (mWaitingRoomFinishedFromCode) return;
if (response == Activity.RESULT_OK) {
// (start game)
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (getContext()!=null) {
Player[] players = getParticipantPlayers();
if (players!=null && players.length>0) {
startGame(players);
}
}
}
}, 1000);
}
else if (response == Activity.RESULT_CANCELED) {
// Waiting room was dismissed with the back button. The meaning of this
// action is up to the game. You may choose to leave the room and cancel the
// match, or do something else like minimize the waiting room and
// continue to connect in the background.
// in this example, we take the simple approach and just leave the room:
Games.RealTimeMultiplayer.leave(((MainActivity) getActivity()).getGoogleApiClient(), roomUpdateListener, mRoomId);
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
else if (response == GamesActivityResultCodes.RESULT_LEFT_ROOM) {
// player wants to leave the room.
Games.RealTimeMultiplayer.leave(((MainActivity) getActivity()).getGoogleApiClient(), roomUpdateListener, mRoomId);
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
}
}
private RoomUpdateListener roomUpdateListener = new RoomUpdateListener() {
#Override
public void onJoinedRoom(int statusCode, Room room) {
if (getContext()!=null) {
roomCreatorId = room.getCreatorId();
mRoomId = room.getRoomId();
mParticipants.clear();
mParticipants.addAll(room.getParticipants());
// setCurrentPlayerParticipantId();
if (statusCode != GamesStatusCodes.STATUS_OK) {
// let screen go to sleep
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// show error message, return to main screen.
Toast.makeText(getContext(), "Error while joining room.", Toast.LENGTH_SHORT).show();
showRoomUi();
}
// get waiting room intent
Intent i = Games.RealTimeMultiplayer.getWaitingRoomIntent(((MainActivity) getActivity()).getGoogleApiClient(), room, MIN_PLAYERS);
startActivityForResult(i, RC_WAITING_ROOM);
}
}
#Override
public void onRoomCreated(int statusCode, Room room) {
if (getContext()!=null) {
roomCreatorId = room.getCreatorId();
mRoomId = room.getRoomId();
mParticipants.clear();
mParticipants.addAll(room.getParticipants());
// setCurrentPlayerParticipantId();
if (statusCode != GamesStatusCodes.STATUS_OK) {
// let screen go to sleep
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// show error message, return to main screen.
Toast.makeText(getContext(), "Error creating room.", Toast.LENGTH_SHORT).show();
showRoomUi();
}
// get waiting room intent
Intent i = Games.RealTimeMultiplayer.getWaitingRoomIntent(((MainActivity) getActivity()).getGoogleApiClient(), room, MIN_PLAYERS);
startActivityForResult(i, RC_WAITING_ROOM);
}
}
#Override
public void onLeftRoom(int i, String s) {
if (getContext()!=null) {
// remove the flag that keeps the screen on
mRoomId = null;
}
}
#Override
public void onRoomConnected(int statusCode, Room room) {
if (getContext()!=null) {
roomCreatorId = room.getCreatorId();
mRoomId = room.getRoomId();
mParticipants.clear();
mParticipants.addAll(room.getParticipants());
// setCurrentPlayerParticipantId();
if (statusCode != GamesStatusCodes.STATUS_OK) {
// let screen go to sleep
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// show error message, return to main screen.
Toast.makeText(getContext(), "Error connecting to room.", Toast.LENGTH_SHORT).show();
showRoomUi();
}
}
}
};
private RoomStatusUpdateListener roomStatusUpdateListener = new RoomStatusUpdateListener() {
#Override
public void onRoomConnecting(Room room) {
if (getContext()!=null) {
mParticipants.clear();
mParticipants.addAll(room.getParticipants());
}
}
#Override
public void onRoomAutoMatching(Room room) {
if (getContext()!=null) {
mParticipants.clear();
mParticipants.addAll(room.getParticipants());
}
}
#Override
public void onPeerInvitedToRoom(Room room, List<String> list) {
if (getContext()!=null) {
mParticipants.clear();
mParticipants.addAll(room.getParticipants());
}
}
#Override
public void onPeerJoined(Room room, List<String> list) {
if (getContext()!=null) {
mParticipants.clear();
mParticipants.addAll(room.getParticipants());
}
}
#Override
public void onConnectedToRoom(Room room) {
if (getContext()!=null) {
mMyId = room.getParticipantId(Games.Players.getCurrentPlayerId(((MainActivity) getActivity()).getGoogleApiClient()));
mParticipants.clear();
mParticipants.addAll(room.getParticipants());
}
}
#Override
public void onDisconnectedFromRoom(Room room) {
if (getContext()!=null) {
// leave the room
Games.RealTimeMultiplayer.leave(((MainActivity) getActivity()).getGoogleApiClient(), roomUpdateListener, room.getRoomId());
// clear the flag that keeps the screen on
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// show error message and return to main screen
Toast.makeText(getContext(), "Network error.", Toast.LENGTH_SHORT).show();
showRoomUi();
}
}
#Override
public void onP2PConnected(String s) {
}
#Override
public void onP2PDisconnected(String s) {
}
#Override
public void onPeersConnected(Room room, List<String> peers) {
if (getContext()!=null) {
mParticipants.clear();
mParticipants.addAll(room.getParticipants());
if (mPlaying) {
// add new player to an ongoing game
} else if (shouldStartGame(room)) {
// start game!
}
}
}
#Override
public void onPeersDisconnected(Room room, List<String> peers) {
if (getContext()!=null) {
mParticipants.clear();
mParticipants.addAll(room.getParticipants());
if (mPlaying) {
// do game-specific handling of this -- remove player's avatar
// from the screen, etc. If not enough players are left for
// the game to go on, end the game and leave the room.
}
else if (shouldCancelGame(room)) {
// cancel the game
Games.RealTimeMultiplayer.leave(((MainActivity) getActivity()).getGoogleApiClient(), roomUpdateListener, room.getRoomId());
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
showRoomUi();
}
}
}
#Override
public void onPeerLeft(Room room, List<String> peers) {
if (getContext()!=null) {
mParticipants.clear();
mParticipants.addAll(room.getParticipants());
// peer left -- see if game should be canceled
if (!mPlaying && shouldCancelGame(room)) {
Games.RealTimeMultiplayer.leave(((MainActivity) getActivity()).getGoogleApiClient(), roomUpdateListener, room.getRoomId());
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
showRoomUi();
}
}
}
#Override
public void onPeerDeclined(Room room, List<String> peers) {
if (getContext()!=null) {
mParticipants.clear();
mParticipants.addAll(room.getParticipants());
// peer declined invitation -- see if game should be canceled
if (!mPlaying && shouldCancelGame(room)) {
Games.RealTimeMultiplayer.leave(((MainActivity) getActivity()).getGoogleApiClient(), roomUpdateListener, room.getRoomId());
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
showRoomUi();
}
}
}
};
private RealTimeMessageReceivedListener realTimeMessageReceivedListener = new RealTimeMessageReceivedListener() {
#Override
public void onRealTimeMessageReceived(RealTimeMessage realTimeMessage) {
if (getContext()!=null) {
if (realTimeMessage.isReliable()) {
handleReliableMessages(realTimeMessage.getMessageData());
}
}
}
};
Any help is appreciated. Thank you.
AFAIK, that's just how the API was designed and is working as intended.
As mentioned in this documentation, you should leave the active room whenever your game goes into the background.
For additional insights (from Bruno Oliveira), you may want to see these related SO posts:
When a peer disconnected from a room in google play services
Google Play Game Services - How to Not Leave Room onPause
Though, you may also opt to try this suggested solution. Try editing BaseGameActivity.onStop() and remove gamehelper.onStop(). With this, gamesclient will only stopped in onDestroy. It might be a good option but I haven't actually tried it.
I want load data from server and show into RecyclerView, for connection library i use Retrofit. and in my application i check internet connection! if connected load data else show another layout.
My codes:
boolean isConnected = ConnectivityReceiver.isConnected();
...
private void loadDataCheckNet() {
loadData(isConnected);
}
private void loadData(boolean isConnect) {
if (isConnect) {
Retrofit_ApiInterface apiInterface = Retrofit_ApiClient.getClient().create(Retrofit_ApiInterface.class);
Call<R_SearchModelResponse> call = apiInterface.getSearchResponse(searchText);
call.enqueue(new Callback<R_SearchModelResponse>() {
#Override
public void onResponse(Call<R_SearchModelResponse> call, Response<R_SearchModelResponse> response) {
if (response != null) {
models.addAll(response.body().getPosts());
mAdapter.notifyDataSetChanged();
if (mAdapter.getItemCount() > 0) {
search_recycler.setAdapter(mAdapter);
searchLoadLayout.setVisibility(View.GONE);
} else {
empty_layout.setVisibility(View.VISIBLE);
searchLoadLayout.setVisibility(View.GONE);
}
} else {
searchLoadLayout.setVisibility(View.VISIBLE);
TastyToast.makeText(context, "Error", TastyToast.LENGTH_LONG, TastyToast.ERROR);
}
mAdapter.notifyDataSetChanged();
searchCheckNet.setVisibility(View.GONE);
}
#Override
public void onFailure(Call<R_SearchModelResponse> call, Throwable t) {
Log.e("CatResponseError", "Error : " + t);
}
});
} else {
searchCheckNet.setVisibility(View.VISIBLE);
if (mAdapter != null) {
mAdapter.clear();
search_recycler.setAdapter(mAdapter);
}
searchCheckNetButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mAdapter.notifyDataSetChanged();
loadDataCheckNet();
}
});
}
}
When running application and isConnected to internet application is ok, load data very good! but when disconnect internet and connect again, load data from server and again duplicate is!
For example : if you have 3 post, post#1,post#2,post#3 when connected to internet load again this three posts! post#1,post#2,post#3,post#1,post#2,post#3 .
How can i fix this problem? Thanks all <3
You just add this models.clear(); into your public void onResponse method.
#Override
public void onResponse(Call<R_SearchModelResponse> call, Response<R_SearchModelResponse> response) {
if (response != null) {
models.clear();
models.addAll(response.body().getPosts());
mAdapter.notifyDataSetChanged();
if (mAdapter.getItemCount() > 0) {
search_recycler.setAdapter(mAdapter);
searchLoadLayout.setVisibility(View.GONE);
} else {
empty_layout.setVisibility(View.VISIBLE);
searchLoadLayout.setVisibility(View.GONE);
}
You're just adding items to your models container, which I assume is some sort of list, you yes, you will have duplicates. You should clear your list before adding new items to it.
Of course, the data is duplicated because you added new data into the list without clearing old data.
One simple fix is, add this line:
models.clear();
before this line:
models.addAll(response.body().getPosts());
By the way, you should set the RecycleView adapter right after you initialized the adapter in onCreate(), there is no point in setting the same adapter to the RecycleView over and over again every time the data is Updated.
UPDATE
Define a Method
public void clearData() {
//for remving list data
int size = this.models.size();
if (size > 0) {
for (int i = 0; i < size; i++) {
this.models.remove(i);
}
this.notifyItemRangeRemoved(0, size);
}
}
call the method before like this
clearData();
models.addAll(response.body().getPosts());