Pass value from CustomDialog to the main Activity - android

public class CustomDialog extends Dialog {
public int result = -1;
public CustomDialog(Context context, int theme) {
super(context, theme);
RadioGroup radioGroup = (RadioGroup) findViewById(R.id.rdbGp1);
radioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
public void onCheckedChanged(RadioGroup arg0, int arg1)
{
result = arg1;
Log.i("Dialog", "Result="+result);
cancel();
}
});
}
public CustomDialog(Context context) {
super(context);
}
/**
* Helper class for creating a custom dialog
*/
public static class Builder {
private Context context;
private String title;
private String message;
private String positiveButtonText;
private String negativeButtonText;
private View contentView;
private DialogInterface.OnClickListener
positiveButtonClickListener,
negativeButtonClickListener;
public Builder(Context context) {
this.context = context;
}
/**
* Set the Dialog message from String
* #param title
* #return
*/
public Builder setMessage(String message) {
this.message = message;
return this;
}
/**
* Set the Dialog message from resource
* #param title
* #return
*/
public Builder setMessage(int message) {
this.message = (String) context.getText(message);
return this;
}
/**
* Set the Dialog title from resource
* #param title
* #return
*/
public Builder setTitle(int title) {
this.title = (String) context.getText(title);
return this;
}
/**
* Set the Dialog title from String
* #param title
* #return
*/
public Builder setTitle(String title) {
this.title = title;
return this;
}
/**
* Set a custom content view for the Dialog.
* If a message is set, the contentView is not
* added to the Dialog...
* #param v
* #return
*/
public Builder setContentView(View v) {
this.contentView = v;
return this;
}
/**
* Set the positive button resource and it's listener
* #param positiveButtonText
* #param listener
* #return
*/
public Builder setPositiveButton(int positiveButtonText,
DialogInterface.OnClickListener listener) {
this.positiveButtonText = (String) context
.getText(positiveButtonText);
this.positiveButtonClickListener = listener;
return this;
}
/**
* Set the positive button text and it's listener
* #param positiveButtonText
* #param listener
* #return
*/
public Builder setPositiveButton(String positiveButtonText,
DialogInterface.OnClickListener listener) {
this.positiveButtonText = positiveButtonText;
this.positiveButtonClickListener = listener;
return this;
}
/**
* Set the negative button resource and it's listener
* #param negativeButtonText
* #param listener
* #return
*/
public Builder setNegativeButton(int negativeButtonText,
DialogInterface.OnClickListener listener) {
this.negativeButtonText = (String) context
.getText(negativeButtonText);
this.negativeButtonClickListener = listener;
return this;
}
/**
* Set the negative button text and it's listener
* #param negativeButtonText
* #param listener
* #return
*/
public Builder setNegativeButton(String negativeButtonText,
DialogInterface.OnClickListener listener) {
this.negativeButtonText = negativeButtonText;
this.negativeButtonClickListener = listener;
return this;
}
/**
* Create the custom dialog
*/
public CustomDialog create() {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// instantiate the dialog with the custom Theme
final CustomDialog dialog = new CustomDialog(context,
R.style.Dialog);
dialog.setOnCancelListener(new OnCancelListener()
{
public void onCancel(DialogInterface arg0)
{
Log.i("FooDialog", "Result="+dialog.result);
}
});
View layout = inflater.inflate(R.layout.credits, null);
dialog.addContentView(layout, new LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
// set the dialog title
((TextView) layout.findViewById(R.id.title)).setText(title);
// set the confirm button
if (positiveButtonText != null) {
((Button) layout.findViewById(R.id.positiveButton))
.setText(positiveButtonText);
if (positiveButtonClickListener != null) {
((Button) layout.findViewById(R.id.positiveButton))
.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
positiveButtonClickListener.onClick(
dialog,
DialogInterface.BUTTON_POSITIVE);
}
});
}
} else {
// if no confirm button just set the visibility to GONE
layout.findViewById(R.id.positiveButton).setVisibility(
View.GONE);
}
// set the cancel button
if (negativeButtonText != null) {
((Button) layout.findViewById(R.id.negativeButton))
.setText(negativeButtonText);
if (negativeButtonClickListener != null) {
((Button) layout.findViewById(R.id.negativeButton))
.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
negativeButtonClickListener.onClick(
dialog,
DialogInterface.BUTTON_NEGATIVE);
}
});
}
} else {
// if no confirm button just set the visibility to GONE
layout.findViewById(R.id.negativeButton).setVisibility(
View.GONE);
}
// set the content message
if (contentView != null) {
// if no message set
// add the contentView to the dialog body
((LinearLayout) layout.findViewById(R.id.content))
.removeAllViews();
((LinearLayout) layout.findViewById(R.id.content))
.addView(contentView,
new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
}
dialog.setContentView(layout);
return dialog;
}
}
}
Hello i am building android app and i am trying to return selected RadioButton id from the custom dialog to the main acivity but the app force closes on this line radioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener()
Can somebody give some hints thank you

Make sure you imported the good class for that event
android.widget.RadioGroup.OnCheckedChangeListener
and not the Compound Button version.

Related

Change Imageview of Alertdialog as per the result

I want to develop the UI in which user will touch the touch pad and if he is registered user of the system , he will be verified by my app. So to indicate that I want to change the fingerprint image by green (valid user) , red (invalid user). So I have created the fragment in which I am getting that result in following two methods
#Override
public void authenticate() {
Log.d(TAG, "authoticate: ");
result = "Yes";
//customBuilder.setImage(R.drawable.ic_fingerprint_pressed);//tried but not working
}
#Override
public void errorAuthenticate() {
Log.d(TAG, "fail: ");
result = "No";
// customBuilder.setImage(R.drawable.ic_fingerprint_pressed_error);//tried but not working
}
Now in same fragment I have created the CustomDialog to show the above images which will be change dynamically. Code for CustomDialog class is given below
public class CustomDialog extends AlertDialog {
public CustomDialog(Context context, int theme) {
super(context, theme);
}
public CustomDialog(Context context) {
super(context);
}
/**
* Helper class for creating a custom dialog
*/
public static class Builder {
private Context context;
private String title;
private int res;
private String message;
private String positiveButtonText;
private String negativeButtonText;
private View contentView;
private DialogInterface.OnClickListener
positiveButtonClickListener,
negativeButtonClickListener;
public Builder(Context context) {
this.context = context;
}
public Builder setMessage(String message) {
this.message = message;
return this;
}
public Builder setMessage(int message) {
this.message = (String) context.getText(message);
return this;
}
/**
* Set the Dialog title from resource
* #param title
* #return
*/
public Builder setTitle(int title) {
this.title = (String) context.getText(title);
return this;
}
/**
* Set the Dialog title from String
* #param title
* #return
*/
public Builder setTitle(String title) {
this.title = title;
return this;
}
public Builder setImage(int res){
this.res = res;
return this;
}
/**
* Set a custom content view for the Dialog.
* If a message is set, the contentView is not
* added to the Dialog...
* #param v
* #return
*/
public Builder setContentView(View v) {
this.contentView = v;
return this;
}
/**
* Set the positive button resource and it's listener
* #param positiveButtonText
* #param listener
* #return
*/
public Builder setPositiveButton(int positiveButtonText,
DialogInterface.OnClickListener listener) {
this.positiveButtonText = (String) context
.getText(positiveButtonText);
this.positiveButtonClickListener = listener;
return this;
}
/**
* Set the positive button text and it's listener
* #param positiveButtonText
* #param listener
* #return
*/
public Builder setPositiveButton(String positiveButtonText,
DialogInterface.OnClickListener listener) {
this.positiveButtonText = positiveButtonText;
this.positiveButtonClickListener = listener;
return this;
}
/**
* Set the negative button resource and it's listener
* #param negativeButtonText
* #param listener
* #return
*/
public Builder setNegativeButton(int negativeButtonText,
DialogInterface.OnClickListener listener) {
this.negativeButtonText = (String) context
.getText(negativeButtonText);
this.negativeButtonClickListener = listener;
return this;
}
/**
* Set the negative button text and it's listener
* #param negativeButtonText
* #param listener
* #return
*/
public Builder setNegativeButton(String negativeButtonText,
DialogInterface.OnClickListener listener) {
this.negativeButtonText = negativeButtonText;
this.negativeButtonClickListener = listener;
return this;
}
/**
* Create the custom dialog
*/
public CustomDialog create() {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// instantiate the dialog with the custom Theme
final CustomDialog dialog = new CustomDialog(context,
R.style.Dialog);
View layout = inflater.inflate(R.layout.capture_finger_touch, null);
// dialog.addContentView(layout, new ViewGroup.LayoutParams(
// ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
// set the dialog title
((ImageView) layout.findViewById(R.id.imgView)).setImageResource(res);
// set the confirm button
if (positiveButtonText != null) {
((Button) layout.findViewById(R.id.btn))
.setText(positiveButtonText);
if (positiveButtonClickListener != null) {
((Button) layout.findViewById(R.id.btn))
.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
positiveButtonClickListener.onClick(
dialog,
DialogInterface.BUTTON_POSITIVE);
}
});
}
} else {
// if no confirm button just set the visibility to GONE
layout.findViewById(R.id.btn).setVisibility(
View.GONE);
}
dialog.setView(layout);
return dialog;
}
}
}
And I have used above CustomDialog by following way
public static String result = "No Found";
CustomDialog.Builder customBuilder = new CustomDialog.Builder(getActivity());
public void captureFingerPrintTouchCustom() {
if (result.equalsIgnoreCase("Yes")) {
customBuilder.setImage(R.drawable.ic_fingerprint_pressed);
} else if (result.equalsIgnoreCase("No")) {
customBuilder.setImage(R.drawable.ic_fingerprint_pressed_error);
//rl.startAnimation(animation);
} else customBuilder.setImage(R.drawable.ic_fingerprint_for_capture);
customBuilder.setPositiveButton("OK2", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog = customBuilder.create();
alertDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
alertDialog.setCanceledOnTouchOutside(false);
alertDialog.setCancelable(false);
alertDialog.show();
}
Here as per the result value I want to change the image of customdialog.
capture_finger_touch.xml code is given below
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="#+id/rl"
android:layout_width="#dimen/alert_dialog_size"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:background="#drawable/rounded_white_background"
android:padding="#dimen/view_internal_space">
<ImageView
android:id="#+id/imgView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:background="#drawable/key_bg_square"
android:src="#drawable/ic_fingerprint_for_capture" />
<Button
android:id="#+id/btn"
style="#style/button_style"
android:layout_height="#dimen/btnHeight"
android:layout_width="wrap_content"
android:layout_below="#+id/imgView"
android:layout_centerHorizontal="true"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:textColor="#color/white"
android:textSize="#dimen/BTC_title_size"
android:textStyle="bold" />
</RelativeLayout>
</RelativeLayout>
But problem is that its not changing the image dynamically. CustomDialog is created like this,
I would suggest you to extend DialogFragment.class, inflate there you layout and communicate with it in you Activity or Fragment
public class FingerprintDialog extends AppCompatDialogFragment implements View.OnClickListener {
private DialogFingerprintBinding binding;
private Listener listener;
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
listener = (Listener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + " implement Listener");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//if you use databinding
//binding = DataBindingUtil.inflate(LayoutInflater.from(getContext()), R.layout.XXX, null, false);
//binding.buttonCancel.setOnClickListener(this);
View view = inflater.inflate(R.layout.XXX, container, false);
Button button = view.findViewById(R.id.button);
getDialog().setCanceledOnTouchOutside(false);
if (getDialog().getWindow() != null) {
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
//return binding.getRoot(); for binding
return view;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
listener.cancel();
break;
default:
break;
}
}
public void changeImage(//posible resource) {
//change Image here
}
public interface Listener {
void cancel();
}
}
And then create instance of this dialog nad show it using method DialogFragment#show
You need to setImageResource to ImageView as follows:
private fingerPrintImageView;
public CustomDialog create() {fingerPrintImageView = ((ImageView) layout.findViewById(R.id.imgView)).setImageResource(res);}
public Builder setImage(int res){this.res = res;fingerPrintImageView.setImageResource(res); return this;}

Recyler View with multiple toggle button checking the button randomly on scroll

I have a recycler view with with multiple toggle buttons on click of which the state is changed and the newly updated state is sent to the server by calling a service on changing the state of the toggle button.
The problem i am facing is that whenever the recycler view is scrolled the toggle buttons are getting checked randomly because of the recycling of the views and the service is called multiple times at the same time, because of which an indeterminate progress bar is shown.
I have tried multiple ways to handle this by intially setting the adapter to null. and also storing the state of the checked/toggle state of the button.
But nothing seems to help.
Below is the code of the recycler adapter class
public class NotificationsIllnessAdapter extends RecyclerView.Adapter<NotificationsIllnessAdapter.NotificationIllnessViewHolder> {
Context context = null;
ArrayList<NotificationIllnessdata> notificationIllnessdatas;
ArrayList<NotificationIllnessdata> notificationIllnessArraylist = null;
NetworkStatus mNetworkStatus = null;
static AlertDialog mShowDialog = null;
Button mButton_alerts;
public NotificationsIllnessAdapter(Context context,ArrayList<NotificationIllnessdata> notificationIllnessdataArrayList,Button button_alerts) {
this.context = context;
this.notificationIllnessdatas=notificationIllnessdataArrayList;
this.mButton_alerts=button_alerts;
for(int i=0;i<this.notificationIllnessdatas.size();i++)
{
Log.e("nIllnessadapter","inside constructor"+this.notificationIllnessdatas.get(i).getIsNotification());
}
}
#Override
public NotificationIllnessViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
mNetworkStatus = new NetworkStatus(context);
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.notifications_inflater, parent, false);
notificationIllnessArraylist = new ArrayList<>();
NotificationIllnessViewHolder viewHolder = new NotificationIllnessViewHolder(context,v);
viewHolder.setClickListener(new MyClickListener() {
#Override
public void onClickListener(View v, int position, boolean isLongClick) {
Toast.makeText(context,"OnClick",Toast.LENGTH_SHORT).show();
}
});
return viewHolder;
}
#Override
public void onBindViewHolder(final NotificationIllnessViewHolder holder, final int position) {
holder.mTextView_symptom.setText(notificationIllnessdatas.get(position).getIllnessCategory());
if(notificationIllnessdatas.get(position).getIsNotification())
{
Log.e("nIllnessadapter","true"+position);
holder.mToggleButton_symptom.setChecked(true);
}
else
{
Log.e("nIllnessadapter","false"+position);
holder.mToggleButton_symptom.setChecked(false);
}
//in some cases, it will prevent unwanted situations
holder.mToggleButton_symptom.setOnCheckedChangeListener(null);
//if true the togglebutton will be selected else unselected.
holder.mToggleButton_symptom.setChecked(notificationIllnessdatas.get(position).getIsNotification());
holder.mToggleButton_symptom.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
ArrayList<UpdateNotificationRequestData> Updatenoti;
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked)
{
//toggle button enabled
UpdateNotificationsRequestModel requestModel = new UpdateNotificationsRequestModel();
requestModel.setUserID(AppPreferences.readString(context, AppPreferenceNames.sUserid,""));
requestModel.setAppVersion(CommonUtils.APP_VERSION);
requestModel.setDeviceInfo(CommonUtils.DeviceInfo);
requestModel.setDeviceTypeID(CommonUtils.DEVICE_TYPE_ID);
Updatenoti = new ArrayList<UpdateNotificationRequestData>();
UpdateNotificationRequestData requestData = new UpdateNotificationRequestData();
Log.e("illadapter","status-->"+notificationIllnessdatas.get(position).getIsNotification());
requestData.setIsNotification("1");
requestData.setNotificationSettingID(notificationIllnessdatas.get(position).getNotificationSettingID());
Updatenoti.add(requestData);
requestModel.setUpdateNotification(Updatenoti);
/**
* Call the Update Notifications service
*/
if (mNetworkStatus.isNetWorkAvailable(context) == true) {
update_notifications(requestModel);
} else {
CommonUtils.showAlertDialog(context,"No Network Available. Please connect to network");
}
//set the objects last status
holder.mToggleButton_symptom.setChecked(isChecked);
}
else
{
//toggle button disabled
UpdateNotificationsRequestModel requestModel = new UpdateNotificationsRequestModel();
requestModel.setUserID(AppPreferences.readString(context, AppPreferenceNames.sUserid,""));
requestModel.setAppVersion(CommonUtils.APP_VERSION);
requestModel.setDeviceInfo(CommonUtils.DeviceInfo);
requestModel.setDeviceTypeID(CommonUtils.DEVICE_TYPE_ID);
Updatenoti = new ArrayList<UpdateNotificationRequestData>();
UpdateNotificationRequestData requestData = new UpdateNotificationRequestData();
Log.e("illadapter","status 2-->"+notificationIllnessdatas.get(position).getIsNotification());
requestData.setIsNotification("0");
requestData.setNotificationSettingID(notificationIllnessdatas.get(position).getNotificationSettingID());
Updatenoti.add(requestData);
requestModel.setUpdateNotification(Updatenoti);
/**
* Call the UpdateNotifications service
*/
if (mNetworkStatus.isNetWorkAvailable(context) == true) {
update_notifications(requestModel);
} else {
CommonUtils.showAlertDialog(context,"No Network Available. Please connect to network");
}
//set the objects last status
holder.mToggleButton_symptom.setChecked(false);
}
}
});
}
#Override
public int getItemCount() {
return notificationIllnessdatas.size();
}
/**
* View Holder for Adapter
*/
class NotificationIllnessViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
MyClickListener clickListener;
public TextView mTextView_symptom;
public ToggleButton mToggleButton_symptom;
public NotificationIllnessViewHolder(Context context,View itemView) {
super(itemView);
mTextView_symptom = (TextView)itemView.findViewById(R.id.TextView_Symptom);
mToggleButton_symptom = (ToggleButton) itemView.findViewById(R.id.ToggleButton_Symptoms);
}
#Override
public void onClick(View v) {
// If not long clicked, pass last variable as false.
clickListener.onClickListener(v, getPosition(), false);
}
public void setClickListener(MyClickListener clickListener) {
this.clickListener = clickListener;
}
}
/**
* Update the notification settings
*/
public void update_notifications(UpdateNotificationsRequestModel object) {
/**
* Start the progress Bar.
*/
CommonUtils.show_progressbar(context);
/**
* call api
*/
Call<UpdateNotificationsResponseModel> responsecall = VirusApplication.getRestClient().getAPIService().updateNotifications(object);
responsecall.enqueue(new Callback<UpdateNotificationsResponseModel>() {
#Override
public void onResponse(Response<UpdateNotificationsResponseModel> response, Retrofit retrofit) {
/**
* Stop the progress Bar
*/
CommonUtils.stop_progressbar();
if (response.isSuccess()) {
//Server Success
UpdateNotificationsResponseModel responseModel = response.body();
if (responseModel.getErrorCode().equalsIgnoreCase("0")) {
//Data Success
Log.e("nf", "data success");
//CommonUtils.showAlertDialog(context, responseModel.getMessage());
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage(responseModel.getMessage())
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
/**
* Downloads mychildren details.
*/
if (mNetworkStatus.isNetWorkAvailable(context)) {
getNotificationSettings();
} else {
CommonUtils.showAlertDialog(context, context.getString(R.string.network_unavailable));
}
dialog.dismiss();
}
});
mShowDialog = builder.create();
mShowDialog.show();
} else {
CommonUtils.showAlertDialog(context, responseModel.getMessage());
}
} else {
CommonUtils.showAlertDialog(context, "Server Error");
}
}
#Override
public void onFailure(Throwable t) {
/**
* Stop the progress Bar
*/
CommonUtils.stop_progressbar();
}
});
}
/**
* Get Notification Settings
*/
public void getNotificationSettings(){
//hit the getnotifications API to fetch the notification details
CommonUtils.show_progressbar(context);
/**
* Calls WebAPI
*/
Call<NotificationsModel> notificationsModelCall = VirusApplication.getRestClient().getAPIService().notifications(getNotificationsrequest());
notificationsModelCall.enqueue(new Callback<NotificationsModel>() {
#Override
public void onResponse(Response<NotificationsModel> response, Retrofit retrofit) {
/**
* Stops the Progresss bar
*/
CommonUtils.stop_progressbar();
if(response.isSuccess()) {
NotificationsModel notificationsModel = response.body();
if (notificationsModel.getErrorCode().equalsIgnoreCase("0")) {// Data Success
Log.e("notificationsAdapter","data success");
int i = 1;
notificationIllnessArraylist.clear();
for (NotificationIllnessdata notificationIllnessdata : notificationsModel.getNotificationIllnessdata()) {
notificationIllnessArraylist.add(notificationIllnessdata);
Log.e("notificationsAdapter","getnotificationsmethod"+i +notificationIllnessdata.getIsNotification() );
i++;
}
Log.e("sonu", "Symptoms ArraySize-->" + notificationIllnessArraylist.size());
if (notificationIllnessArraylist.size() > 0) {
ArrayList<NotificationIllnessdata> arrayTrue = new ArrayList<NotificationIllnessdata>();
ArrayList<NotificationIllnessdata> arrayFalse = new ArrayList<NotificationIllnessdata>();
for(int j=0;j<notificationIllnessArraylist.size();j++)
{
if(notificationIllnessArraylist.get(j).getIsNotification()){
arrayTrue.add(notificationIllnessArraylist.get(j));
}
else
if(!notificationIllnessArraylist.get(j).getIsNotification())
{
arrayFalse.add(notificationIllnessArraylist.get(j));
}
}
if(notificationIllnessArraylist.size()==arrayTrue.size())
{
mButton_alerts.setText("DeSelect All");
mButton_alerts.setBackgroundResource(R.drawable.togglebutton_on);
}
else
if(notificationIllnessArraylist.size()==arrayFalse.size())
{
mButton_alerts.setText("Select All");
mButton_alerts.setBackgroundResource(R.drawable.togglebutton_off);
}
else {
mButton_alerts.setText("Select All");
mButton_alerts.setBackgroundResource(R.drawable.togglebutton_off);
}
}
}
}
}
#Override
public void onFailure(Throwable t) {
}
});
}
/**
* Request values to Get notifications.
*
* #return map object
*/
public Map<String, Object> getNotificationsrequest() {
Map<String, Object> getChildrenValues = new HashMap<>();
getChildrenValues.put("appVersion", CommonUtils.APP_VERSION);
getChildrenValues.put("deviceTypeID", CommonUtils.DEVICE_TYPE_ID);
getChildrenValues.put("deviceInfo", CommonUtils.DeviceInfo);
getChildrenValues.put("userID", AppPreferences.readString(context, AppPreferenceNames.sUserid, ""));
return getChildrenValues;
}
}
Please help me with this. Have been trying from many days but haven't found any solution even after following many answers on stack overflow.
Try out this :
public class NotificationsIllnessAdapter extends RecyclerView.Adapter<NotificationsIllnessAdapter.NotificationIllnessViewHolder> {
Context context = null;
ArrayList<NotificationIllnessdata> notificationIllnessdatas;
NetworkStatus mNetworkStatus = null;
static AlertDialog mShowDialog = null;
Button mButton_alerts;
public NotificationsIllnessAdapter(Context context,ArrayList<NotificationIllnessdata> notificationIllnessdataArrayList,Button button_alerts) {
this.context = context;
this.mNetworkStatus = new NetworkStatus(context);
this.notificationIllnessdatas=notificationIllnessdataArrayList;
this.mButton_alerts=button_alerts;
}
#Override
public NotificationIllnessViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.notifications_inflater, parent, false);
NotificationIllnessViewHolder viewHolder = new NotificationIllnessViewHolder(context,v);
return viewHolder;
}
#Override
public void onBindViewHolder(final NotificationIllnessViewHolder holder, final int position) {
holder.mTextView_symptom.setText(notificationIllnessdatas.get(position).getIllnessCategory());
holder.mToggleButton_symptom.setChecked(notificationIllnessdatas.get(position).getIsNotification());
holder.mToggleButton_symptom.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
ArrayList<UpdateNotificationRequestData> Updatenoti;
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int position = getAdapterPosition();
if( position == RecyclerView.NO_POSITION ) {
return;
}
if(isChecked)
{
notificationIllnessdatas.get(position).setNotification(true);
}
else
{
notificationIllnessdatas.get(position).setNotification(false);
}
}
});
}
The toggling of checkboxes / toggle buttons happens due to the fact that the states are not maintained in your model class. You already have a isNotification field in your model class, set it as soon as the toggle happens as I've illustrated in the code. I have other code clean up suggestions, but those can wait.
Let me know if you need more clarifications.
Update : Answer only applicable for retaining states of toggle
buttons.

GridView rendered very long time with HTTP response

I'm beginner in Android development. I'm using this library for http requests https://github.com/loopj/android-async-http.
And then I render response JSON in GridView it takes very long time. I'm using progress dialog as preloader, but it's removed before listview is rendered. How I can solve this problem? Thank you.
Here is screenshot of this GridView.
Here is implementation of this activity.
public class LikesActivity extends BottomBarActivity //some custom activity {
List<Anticafe> mAnticafes = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_likes);
/*some code*/
Request.post(Constants.POST_SEARCH_API_LINK, params, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
Gson gson = new GsonBuilder().create();
Request request = gson.fromJson(new String(responseBody), Request.class);
mAnticafes = request.getAnticafes();
renderListView()
}
#Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
hideProcessDialog();
}
});
}
private void renderListView() {
GridView likesList = (GridView) findViewById(R.id.likes_list);
AnticafeAdapter anticafeAdapter = new AnticafeAdapter(this, mAnticafes);
anticafeAdapter.setWidth(getWidth());
likesList.setAdapter(anticafeAdapter);
}
}
Here is full implementaion of adapter.
public class AnticafeAdapter extends BaseAdapter{
public static final String TAG = "image-request";
private Context mContext;
private List<Anticafe> mAnticafes = new ArrayList<>();
private Client mClient;
private View mConvertView;
private int mWidth;
public AnticafeAdapter(Context context, List<Anticafe> anticafes) {
mContext = context;
mAnticafes = anticafes;
}
public void setWidth(int mWidth) {
this.mWidth = (int) (mWidth / 4.7);
}
#Override
public int getCount() {
return mAnticafes.size();
}
#Override
public Anticafe getItem(int position) {
return mAnticafes.get(position);
}
#Override
public long getItemId(int position) {
return getItem(position).getId();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final Anticafe anticafe = getItem(position);
mClient = AnticafeApplication.getInstanse().getClient();
mConvertView = convertView;
final ProgressDialog processDialog = new ProgressDialog(mContext);
processDialog.setMessage("Информация обновляется. Пожалуйста, подождите.");
if(mConvertView == null) {
mConvertView = LayoutInflater.from(mContext).inflate(R.layout.adapter_popular, null);
}
ImageView cover = (ImageView) mConvertView.findViewById(R.id.cover);
CircularImageView logo = (CircularImageView) mConvertView.findViewById(R.id.logo);
final ImageView like = (ImageView) mConvertView.findViewById(R.id.like);
final TextView likesCount = (TextView) mConvertView.findViewById(R.id.likes_count);
TextView name = (TextView) mConvertView.findViewById(R.id.name);
TextView price = (TextView) mConvertView.findViewById(R.id.price);
if(mClient != null) {
final boolean liked = mClient.containsLike(anticafe.getId());
if(liked) {
like.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_like));
} else {
like.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_unlike));
}
} else {
like.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_unlike));
}
likesCount.setText(String.valueOf(anticafe.getTotalLikes()));
name.setText(anticafe.getName());
price.setText(anticafe.getPrices());
Picasso.with(mContext).load(anticafe.getAttachment().getCover()).networkPolicy(NetworkPolicy.OFFLINE).into(cover);
Picasso.with(mContext).load(anticafe.getAttachment().getLogo()).resize(mWidth, mWidth).into(logo);
likeMechanism(anticafe, processDialog, like, likesCount);
name.setOnClickListener(anticafeOpenActivityEvent(anticafe.getId()));
price.setOnClickListener(anticafeOpenActivityEvent(anticafe.getId()));
logo.setOnClickListener(anticafeOpenActivityEvent(anticafe.getId()));
cover.setOnClickListener(anticafeOpenActivityEvent(anticafe.getId()));
BottomBarActivity activity = (BottomBarActivity) this.mContext;
activity.hideProcessDialog();
return mConvertView;
}
private void likeMechanism(final Anticafe anticafe, final ProgressDialog processDialog, final ImageView like, final TextView likesCount) {
like.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (mClient == null) {
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setTitle("Вы не авторизованы")
.setMessage("До тех пор, пока вы не пройдете авторизацию, вы не сможете пользоваться некоторым функционалом нашего приложение. Авторизация займет всего лишь пару минут.")
.setCancelable(false)
.setNegativeButton("Скрыть", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("Авторизоваться", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(mContext, AuthActivity.class);
mContext.startActivity(intent);
Activity activity = ((Activity) mContext);
activity.overridePendingTransition(R.anim.slide_in_left, R.anim.slide_in_right);
}
});
AlertDialog dialog = builder.create();
dialog.show();
} else {
processDialog.show();
RequestParams params = new RequestParams();
params.add("anticafe_id", anticafe.getId() + "");
AuthedRequest.post(Constants.LIKE_API_LINK, params, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
processDialog.hide();
Gson gson = new GsonBuilder().create();
try {
LikeResponse response = gson.fromJson(new String(responseBody, Constants.UTF_8), LikeResponse.class);
if (response.getLikeStatus().equals("unliked")) {
like.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_unlike));
} else if (response.getLikeStatus().equals("liked")) {
like.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_like));
}
likesCount.setText(String.valueOf(response.getTotalLikes()));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} finally {
processDialog.hide();
}
}
#Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
try {
Log.d("json", "onSuccess: " + new String(responseBody, Constants.UTF_8));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} finally {
processDialog.hide();
}
}
});
}
}
});
}
private OnClickListener anticafeOpenActivityEvent(final int id) {
return new OnClickListener() {
#Override
public void onClick(View v) {
Bundle bundle = new Bundle();
bundle.putInt("entity_id", id);
((BottomBarActivity) mContext).openNewActivity(AnticafeActivity.class, bundle);
}
};
}
private static class LikeResponse {
#SerializedName("status")
#Expose
private Integer status;
#SerializedName("error")
#Expose
private Boolean error;
#SerializedName("likeStatus")
#Expose
private String likeStatus;
#SerializedName("totalLikes")
#Expose
private Integer totalLikes;
public LikeResponse(Integer status, Boolean error, String likeStatus, Integer totalLikes) {
this.status = status;
this.error = error;
this.likeStatus = likeStatus;
this.totalLikes = totalLikes;
}
/**
*
* #return
* The status
*/
public Integer getStatus() {
return status;
}
/**
*
* #param status
* The status
*/
public void setStatus(Integer status) {
this.status = status;
}
/**
*
* #return
* The error
*/
public Boolean getError() {
return error;
}
/**
*
* #param error
* The error
*/
public void setError(Boolean error) {
this.error = error;
}
/**
*
* #return
* The likeStatus
*/
public String getLikeStatus() {
return likeStatus;
}
/**
*
* #param likeStatus
* The likeStatus
*/
public void setLikeStatus(String likeStatus) {
this.likeStatus = likeStatus;
}
/**
*
* #return
* The totalLikes
*/
public Integer getTotalLikes() {
return totalLikes;
}
/**
*
* #param totalLikes
* The totalLikes
*/
public void setTotalLikes(Integer totalLikes) {
this.totalLikes = totalLikes;
}
}
}
You dont show any code to say exactly what is you problem.
But any way its better to use a third party library for loading images from web such as picasso:
http://square.github.io/picasso
this library load your images smoothly and mange caches by itself.
UPDATE:
Other option is that you dont use viewHolder design pattern in your getView method in your adapter class.
In your current code you call findViewById method in every cell of your gridView but you must call it only first time.
to resolve this problem you should use viewHolder design pattern.
An exampple of getView method with view Holder :
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolderItem viewHolder;
/*
* The convertView argument is essentially a "ScrapView" as described is Lucas post
* http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/
* It will have a non-null value when ListView is asking you recycle the row layout.
* So, when convertView is not null, you should simply update its contents instead of inflating a new row layout.
*/
if(convertView==null){
// inflate the layout
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
convertView = inflater.inflate(layoutResourceId, parent, false);
// well set up the ViewHolder
viewHolder = new ViewHolderItem();
viewHolder.textViewItem = (TextView) convertView.findViewById(R.id.textViewItem);
// store the holder with the view.
convertView.setTag(viewHolder);
}else{
// we've just avoided calling findViewById() on resource everytime
// just use the viewHolder
viewHolder = (ViewHolderItem) convertView.getTag();
}
// object item based on the position
ObjectItem objectItem = data[position];
// assign values if the object is not null
if(objectItem != null) {
// get the TextView from the ViewHolder and then set the text (item name) and tag (item ID) values
viewHolder.textViewItem.setText(objectItem.itemName);
viewHolder.textViewItem.setTag(objectItem.itemId);
}
return convertView;
}
Example of View holder class (define your view elements in this class) :
static class ViewHolderItem {
TextView textViewItem;
}
for more info see this :
https://www.javacodegeeks.com/2013/09/android-viewholder-pattern-example.html

Memory Leak due to PopupWindow

I have a FragmentA. When I click on a button in FragmentA I go to FragmentB. In FragmentB I have a PopupWindow. The PopupWindow have a ViewPager with two pages.
I took help from this code - Emojicon
I have 2 separate classes, View1 and View2, for the views at page 1 and 2 of the ViewPager respectively. Both these classes, View1 and View2, extends a parent class ViewBase.
Here is my problem:
Scenario 1: When I am at FragmentA the memory graph shows 13MB utilization. When I go to FragmentB without showing PopupWindow the memory graph shows 16MB and when I come back to FragmentA it comes down to 13MB. This is good.
Scenario 2: When I am at FragmentA the memory graph shows 13MB utilization. When I go to FragmentB with showing PopupWindow the memory graph shows 20MB and when I come back to FragmentA it doesn't come down to 13MB.
I have tried Eclipse MAT and Heap dump to find out the issue but still no help. I can see in the MAT that FragmentB is still in memory when I come back to FragmentA holding the instances of PopupWindow, View1 and View2. None of them are released. FragmentB should not be in memory.
Please help me out.
Here is my DemoPopupWindow.java
public class DemoPopupWindow extends PopupWindow {
// Views
private TabLayout mTabLayout;
private CustomViewPager mViewPager;
private PagerAdapter mViewPagerAdapter;
private RelativeLayout mLayout;
private View mRootView;
// Variables
private int mGreyColor, mPrimaryColor;
private OnSoftKeyboardOpenCloseListener onSoftKeyboardOpenCloseListener;
private int keyBoardHeight = 0;
private Boolean pendingOpen = false;
private Boolean isOpened = false;
private Context mContext;
ViewTreeObserver.OnGlobalLayoutListener mGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect r = new Rect();
mRootView.getWindowVisibleDisplayFrame(r);
int screenHeight = mRootView.getRootView().getHeight();
int heightDifference = screenHeight - (r.bottom);
if (heightDifference > 100) {
keyBoardHeight = heightDifference;
setSize(WindowManager.LayoutParams.MATCH_PARENT, keyBoardHeight);
if (isOpened == false) {
if (onSoftKeyboardOpenCloseListener != null)
onSoftKeyboardOpenCloseListener.onKeyboardOpen(keyBoardHeight);
}
isOpened = true;
if (pendingOpen) {
showAtBottom();
pendingOpen = false;
}
} else {
isOpened = false;
if (onSoftKeyboardOpenCloseListener != null)
onSoftKeyboardOpenCloseListener.onKeyboardClose();
}
}
};
/**
* Constructor
* #param rootView
* #param mContext
*/
public DemoPopupWindow(View rootView, Context mContext){
super(mContext);
this.mContext = mContext;
this.mRootView = rootView;
Resources resources = mContext.getResources();
View customView = createCustomView(resources);
setContentView(customView);
setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
setSize((int) mContext.getResources().getDimension(R.dimen.keyboard_height), WindowManager.LayoutParams.MATCH_PARENT);
}
/**
* Set keyboard close listener
* #param listener
*/
public void setOnSoftKeyboardOpenCloseListener(OnSoftKeyboardOpenCloseListener listener){
this.onSoftKeyboardOpenCloseListener = listener;
}
/**
* Show PopupWindow
*/
public void showAtBottom(){
showAtLocation(mRootView, Gravity.BOTTOM, 0, 0);
}
/**
* Show PopupWindow at bottom
*/
public void showAtBottomPending(){
if(isKeyBoardOpen())
showAtBottom();
else
pendingOpen = true;
}
/**
* Check whether keyboard is open or not
* #return
*/
public Boolean isKeyBoardOpen(){
return isOpened;
}
/**
* Set soft keyboard size
*/
public void setSizeForSoftKeyboard(){
mRootView.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener);
}
/**
* Remove global layout listener
*/
public void removeGlobalListener() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
mRootView.getViewTreeObserver().removeGlobalOnLayoutListener(mGlobalLayoutListener);
} else {
mRootView.getViewTreeObserver().removeOnGlobalLayoutListener(mGlobalLayoutListener);
}
}
/**
* Set PopupWindow size
* #param width
* #param height
*/
public void setSize(int width, int height){
keyBoardHeight = height;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, keyBoardHeight);
mLayout.setLayoutParams(params);
setWidth(width);
setHeight(height);
}
/**
* Create PopupWindow View
* #return
*/
private View createCustomView(Resources resources) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.popup, null, false);
mViewPager = (CustomViewPager) view.findViewById(R.id.pager);
mLayout = (RelativeLayout) view.findViewById(R.id.layout);
mViewPagerAdapter = new ViewPagerAdapter(
Arrays.asList(
new View1(mContext, this),
new View2(mContext, this)
)
);
mViewPager.setAdapter(mViewPagerAdapter);
mPrimaryColor = resources.getColor(R.color.color_primary);
mGreyColor = resources.getColor(R.color.grey_color);
mTabLayout = (TabLayout) view.findViewById(R.id.tabs);
mTabLayout.addTab(mTabLayout.newTab());
mTabLayout.addTab(mTabLayout.newTab());
mTabLayout.setupWithViewPager(mViewPager);
return view;
}
/**
* ViewPager Adapter
*/
private static class ViewPagerAdapter extends PagerAdapter {
private List<ViewBase> views;
public ViewPagerAdapter(List<ViewBase> views) {
super();
this.views = views;
}
#Override
public int getCount() {
return views.size();
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
View v = views.get(position).mRootView;
((ViewPager)container).addView(v, 0);
return v;
}
#Override
public void destroyItem(ViewGroup container, int position, Object view) {
((ViewPager)container).removeView((View)view);
}
#Override
public boolean isViewFromObject(View view, Object key) {
return key == view;
}
}
/**
* Soft keyboard open close listener
*/
public interface OnSoftKeyboardOpenCloseListener{
void onKeyboardOpen(int keyBoardHeight);
void onKeyboardClose();
}
}
Please note that I haven't pasted complete PopupWindow class here but only the necessary part.
Here is how I am using this DemoPopupWindow in my FragmentB
mPopupWindow = new DemoPopupWindow(mLayout, getActivity());
mPopupWindow.setSizeForSoftKeyboard();
// If the text keyboard closes, also dismiss the PopupWindow
mPopupWindow.setOnSoftKeyboardOpenCloseListener(new DemoPopupWindow.OnSoftKeyboardOpenCloseListener() {
#Override
public void onKeyboardOpen(int keyBoardHeight) {
}
#Override
public void onKeyboardClose() {
if (mPopupWindow.isShowing())
mPopupWindow.dismiss();
}
});
In FragmentB onDestroy I am calling this method to remove GlobalLayoutListener
mPopupWindow.removeGlobalListener();
I have a button in FragmentB to show and dismiss PopupWindow.
Here is my ViewBase.java
public class ViewBase {
public View mRootView;
DemoPopupWindow mPopup;
private Context mContext;
public ViewBase (Context context, DemoPopupWindow popup) {
mContext = context;
mPopup = popup;
}
public ViewBase () {
}
}
Here is my View1
public class View1 extends ViewBase{
// Views
public View mRootView;
DemoPopupWindow mPopup;
private LinearLayout mLayoutText;
// Variables
private Context mContext;
private List<String> mText;
/**
* Constructor
*/
public View1(Context context, DemoPopupWindow popup) {
super(context, popup);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
mPopup = popup;
mRootView = inflater.inflate(R.layout.fragment_view1, null);
mContext = context;
// Set parent class rootview
super.mRootView = mRootView;
registerViews(mRootView);
registerListeners();
populateText();
}
/**
* Register all the views
* #param view
*/
private void registerViews(View view) {
mLayoutText = (LinearLayout) view.findViewById(R.id.view1_layout);
mText = TextManager.getInstance().getText();
}
/**
* Populate text
*/
private void populateText() {
int length = mText.size();
for(int i=0; i<length; i++) {
addNewText(mText.get(i).getText());
}
}
/**
* Add new text
* #param text
*/
private void addNewText(final String text) {
TextView textView = createTextView(text);
mLayoutText.addView(textView);
textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Do something
}
});
}
/**
* Create textview
* #param text
* #return
*/
private TextView createTextView(final String text) {
TextView textView = new TextView(mContext);
FlowLayout.LayoutParams params = new FlowLayout.LayoutParams(FlowLayout.LayoutParams.WRAP_CONTENT, 40);
params.setMargins(4, 4, 0, 0);
textView.setLayoutParams(params);
textView.setClickable(true);
textView.setGravity(Gravity.CENTER);
textView.setPadding(10, 0, 10, 0);
textView.setText(text);
textView.setTextSize(20);
return textView;
}
}
EDIT AGAIN:
I have found the issue but I dont know how to fix it. The problem is with mGlobalLayoutListener. This is holding the reference of some view. If I don't use GlobalLayoutListener at all then the FragmentB instance is getting removed from the memory.
Even after calling removeGlobalLayout(), this listener is not getting released. Please help me out.
are you sure CustomPopupWindow is causing you memory leak? Have you done garbage collection before running heap dump, maybe there is no leak at all..?
It's called onDestroy in FragmentB with popup when you goes back to fragmentA?
How to remove safely GlobalLayoutListener ?
Caution of your Android version, since api is deprecated! :)
Can you try this
if (Build.VERSION.SDK_INT < 16) {
v.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
} else {
v.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
}

BaseAdapter.notifyDatasetChanged() not updating the ListView

why does my listview not update when I call notifyDatasetChanged() ?
the only way I can make it display the data is, to call setAdatper() on the ListView again... i also tried to call it via runOnUIThread() which did not change anything
The Adapter
/**
* Adapter to provide the data for the online scores
*
* #author soh#zolex
*
*/
public class OnlineScoresAdapter extends BaseAdapter {
private Context context;
private List<ScoreItem> scores = new ArrayList<ScoreItem>();
/**
* Constructor
*
* #param Context context
*/
public OnlineScoresAdapter(Context context) {
this.context = context;
}
/**
* Add an item to the adapter
*
* #param item
*/
public void addItem(ScoreItem item) {
this.scores.add(item);
}
/**
* Get the number of scores
*
* #return int
*/
public int getCount() {
return this.scores.size();
}
/**
* Get a score item
*
* #param int pos
* #return Object
*/
public Object getItem(int pos) {
return this.scores.get(pos);
}
/**
* Get the id of a score
*
* #param in pos
* #retrn long
*/
public long getItemId(int pos) {
return 0;
}
/**
* Get the type of an item view
*
* #param int pos
* #return int
*/
public int getItemViewType(int arg0) {
return arg0;
}
/**
* Create the view for a single list item.
* Load it from an xml layout.
*
* #param int pos
* #param View view
* #param ViewGroup viewGroup
* #return View
*/
public View getView(int pos, View view, ViewGroup group) {
LinearLayout layout;
if (view == null) {
layout = (LinearLayout)View.inflate(this.context, R.layout.scoreitem, null);
} else {
layout = (LinearLayout)view;
}
TextView position = (TextView)layout.findViewById(R.id.pos);
TextView time = (TextView)layout.findViewById(R.id.time);
TextView player = (TextView)layout.findViewById(R.id.player);
TextView createdAt = (TextView)layout.findViewById(R.id.created_at);
ScoreItem item = (ScoreItem)getItem(pos);
player.setText(item.player);
position.setText(String.valueOf(new Integer(item.position)) + ".");
time.setText(String.format("%.4f", item.time));
createdAt.setText(item.created_at);
return layout;
}
/**
* Get the number of different views
*
* #return int
*/
public int getViewTypeCount() {
return 1;
}
/**
* Return wheather the items have stable IDs or not
*
* #return boolean
*/
public boolean hasStableIds() {
return false;
}
/**
* Return wheather the list is empty or not
*
* #return boolean
*/
public boolean isEmpty() {
return this.scores.size() == 0;
}
/**
* No need of a data observer
*
* #param DataSetObserver arg0
* #return void
*/
public void registerDataSetObserver(DataSetObserver arg0) {
}
/**
* No need of a data observer
*
* #param DataSetObserver arg0
* #return void
*/
public void unregisterDataSetObserver(DataSetObserver arg0) {
}
/**
* No item should be selectable
*
* #return boolean
*/
public boolean areAllItemsEnabled() {
return false;
}
/**
* No item should be selectable
*
* #param int pos
* #return boolean
*/
public boolean isEnabled(int arg0) {
return false;
}
}
The Activity
The XMLLoaderThread works fine, it's just notifyDatasetChanged seems to do nothing...
/**
* Obtain and display the online scores
*
* #author soh#zolex
*
*/
public class OnlineScoresDetails extends ListActivity {
WakeLock wakeLock;
OnlineScoresAdapter adapter;
boolean isLoading = false;
int chunkLimit = 50;
int chunkOffset = 0;
#Override
/**
* Load the scores and initialize the pager and adapter
*
* #param Bundle savedInstanceState
*/
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
this.wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "racesow");
adapter = new OnlineScoresAdapter(this);
setListAdapter(adapter);
this.loadData();
setContentView(R.layout.listview);
getListView().setOnScrollListener(new OnScrollListener() {
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (totalItemCount > 0 && visibleItemCount > 0 && firstVisibleItem + visibleItemCount >= totalItemCount) {
if (!isLoading) {
loadData();
}
}
}
});
}
public void loadData() {
final ProgressDialog pd = new ProgressDialog(OnlineScoresDetails.this);
pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pd.setMessage("Obtaining scores...");
pd.setCancelable(false);
pd.show();
isLoading = true;
String mapName = getIntent().getStringExtra("map");
XMLLoaderThread t = new XMLLoaderThread("http://racesow2d.warsow-race.net/map_positions.php?name=" + mapName + "&offset=" + this.chunkOffset + "&limit=" + this.chunkLimit, new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
// network error
case 0:
new AlertDialog.Builder(OnlineScoresDetails.this)
.setMessage("Could not obtain the maplist.\nCheck your network connection and try again.")
.setNeutralButton("OK", new OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
finish();
overridePendingTransition(0, 0);
}
})
.show();
break;
// maplist received
case 1:
pd.dismiss();
InputStream xmlStream;
try {
xmlStream = new ByteArrayInputStream(msg.getData().getString("xml").getBytes("UTF-8"));
XMLParser parser = new XMLParser();
parser.read(xmlStream);
NodeList positions = parser.doc.getElementsByTagName("position");
int numPositions = positions.getLength();
for (int i = 0; i < numPositions; i++) {
Element position = (Element)positions.item(i);
ScoreItem score = new ScoreItem();
score.position = Integer.parseInt(parser.getValue(position, "no"));
score.player = parser.getValue(position, "player");
score.time = Float.parseFloat(parser.getValue(position, "time"));
score.created_at = parser.getValue(position, "created_at");
adapter.addItem(score);
}
adapter.notifyDataSetChanged();
chunkOffset += chunkLimit;
isLoading = false;
} catch (UnsupportedEncodingException e) {
new AlertDialog.Builder(OnlineScoresDetails.this)
.setMessage("Internal error: " + e.getMessage())
.setNeutralButton("OK", null)
.show();
}
break;
}
pd.dismiss();
}
});
t.start();
}
/**
* Acquire the wakelock on resume
*/
public void onResume() {
super.onResume();
this.wakeLock.acquire();
}
/**
* Release the wakelock when leaving the activity
*/
public void onDestroy() {
super.onDestroy();
this.wakeLock.release();
}
/**
* Disable animations when leaving the activity
*/
public void onBackPressed() {
this.finish();
this.overridePendingTransition(0, 0);
}
}
A bit late but the answer is you should not implement
public void registerDataSetObserver(DataSetObserver arg0) {
}
public void unregisterDataSetObserver(DataSetObserver arg0) {
}
I just had a simple BaseAdapter working as intended, who stop working after adding those two methods. I asume that "someone" need to observe data changes and such :)
I am not really sure if your implementation of Custom BaseAdapter is correct.
Try changing
public long getItemId(int pos) {
return 0;
}
to
public long getItemId(int pos) {
return pos;
}
I also found this simple tutorial that might be helpful on how to implement BaseAdapter. After you got this down, you can try notifyDataSetChanged() again.
You should call adapter.notifyDataSetChanged() after every manipulation of your dataset. If you're adding items in a batch (e.g. a for-loop), this means you have to put .notifyDataSetChanged in your loop, like so:
for(int i = 0; i < numPositions; i++) {
....
adapter.addItem(score);
adapter.notifyDataSetChanged();
}
Make sure you call adapter.notifyDataSetChanged() from your UI-thread.
If you rather update your adapter once, store your ScoreItems in an ArrayList and after the loop call:
adapter.addAll(scoreList);
adapter.notifyDataSetChanged();
But then again, as far as I'm aware there's really no reason to do that.
Maybe it will be helpful to someone. For the method to work correctly, you should make sure that the following conditions are met:
1) getCount() should return correct items size, e.g.
#Override
public int getCount() {
return allMonthDays.size();
}
2) getItemId(int position) should return different id if item was changed, so it may be not enough to return just position here, e.g.
#Override
public long getItemId(int position) {
return allMonthDays.get(position).getTimestamp();
}
3) getView(int position, View convertView, ViewGroup parent) should return needed View, you should make sure that you update it if you want to reuse old convertView

Categories

Resources