I used fragment in my app and i'm using SQLite to save local data. But when I finished saving data, and I swipe the page, my listView is not refreshed with new data (Only showing old data). I have tried to provide a method notifyDataSetChanged() on my adapter, but it's not working.
My Base Adapter class :
public class LocalDataAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<LocalDataBean> data;
private static LayoutInflater inflater = null;
public LocalDataAdapter(Activity a, ArrayList<LocalDataBean> d) {
activity = a;
data = d;
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public void setItem(ArrayList<LocalDataBean> data){
this.data = data;
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = inflater.inflate(R.layout.list_item, null);
TextView nama_konsumen = (TextView) v.findViewById(R.id.nama_konsumen);
TextView no_telp = (TextView) v.findViewById(R.id.no_telp);
TextView no_hp_cdma = (TextView) v.findViewById(R.id.no_hp_cdma);
TextView no_hp_gsm = (TextView) v.findViewById(R.id.no_hp_gsm);
LocalDataBean obj = (LocalDataBean) getItem(position);
nama_konsumen.setText(obj.getNamaKonsumen());
no_telp.setText(obj.getNoTelp());
no_hp_cdma.setText(obj.getNoCMDA());
no_hp_gsm.setText(obj.getNoGSM());
return v;
}
}
My fragment class :
public class LocalDataFragment extends Fragment {
View view;
Activity act;
SQLHandlerBean utilSql;
ArrayList<LocalDataBean> localdatabean = new ArrayList<LocalDataBean>();
LocalDataAdapter adapter;
ListView list;
public static final String TAG = LocalDataFragment.class.getSimpleName();
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.layout_local_data, null);
act = getActivity();
list = (ListView) view.findViewById(R.id.listViewLocalData);
utilSql = new SQLHandlerBean(this.act);
adapter = new LocalDataAdapter(act, localdatabean);
localdatabean = new ArrayList<LocalDataBean>();
list.setAdapter(adapter);
if (utilSql.ReadAllLocalData().size() < 1) {
Toast.makeText(act, "DATA EMPTY!", Toast.LENGTH_LONG).show();
} else {
localdatabean = utilSql.ReadAllLocalData();
Log.e(TAG, "TOTAL DATA : "+localdatabean.size());
adapter.setItem(localdatabean);
adapter.notifyDataSetChanged();
}
return view;
}
}
Is adapter.notifyDataSetChanged() placement correct?
No, the placement is not in the right place.
As you have placed the notifyDataSetChanged() inside of the onCreateView() method. It will be only invoked 1st time the fragment is launched.
Rather you can add a refresh button in your layout (or in you action bar). And along with the insertion/deletion method of the data, place the notifyDataSetChanged() at the bottom of the click event of that button.
By doing this user can refresh the page whenever they want.
And if you want to refresh the page by swipping the view then, SwipeRefreshLaoyout could be a perfect alternative.
You can check this blog.
Related
I have created a listview. Each item in list view has two UI elements. One is a textview and other is a number picker. Now the issue is that if i click on first number picker to change value, the fourth one also changes and vice versa. Here is my getview function
private class ViewHolder {
public TextView name;
public NumberPicker numberPicker;
public CustomListener listener;
}
public View getView(final int position, #Nullable View convertView, #NonNull final ViewGroup parent) {
ViewHolder holder;
View listItem = convertView;
currentCell=getItem(position);
currentCell.setPosition(position);
if (listItem == null) {
LayoutInflater inflater = LayoutInflater.from(mContext);
listItem = inflater.inflate(R.layout.organ_item, parent, false);
}
holder = new ViewHolder();
holder.name = (TextView) listItem.findViewById(R.id.organName);
holder.numberPicker = (NumberPicker)
listItem.findViewById(R.id.numberPicker);
holder.numberPicker.setMinValue(1);
holder.numberPicker.setMaxValue(10);
holder.numberPicker.setOnValueChangedListener(holder.listener);
holder.numberPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
#Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
currentCell=getItem(position);
View parentRow = (View) picker.getParent();
ListView mListView=(ListView)parentRow.getParent().getParent();
ConstraintLayout constraintLayoutView = (ConstraintLayout) mListView.getChildAt(currentCell.getPosition());
RelativeLayout relativeLayout = (RelativeLayout)constraintLayoutView.getChildAt(0);
NumberPicker p = (NumberPicker) relativeLayout.getChildAt(1);
if(position==currentCell.getPosition())
{
p.setValue(newVal);
}
else
{
p.setValue(oldVal);
}
}
});
//Set the name
TextView organName = (TextView)listItem.findViewById(R.id.organName);
organName.setText(QuickMeditationScreenInfo.getInstance().getScreenNameFromIndex(currentCell.getOrgan()));
return listItem;
}
Also even if i comment out the onValueChangeListener even then the same behaviour occurs which i assume is the default behaviour of number picker in a list. I have spent multiple hours on it but couldn't figure out the solution. I have also debugged the code and when i change a value, the debugger comes into the onValueChange code only once.
You need set numberpicker default value every time
holder = new ViewHolder();
holder.name = (TextView) listItem.findViewById(R.id.organName);
holder.numberPicker = (NumberPicker) ;
holder.numberPicker.setValue(defaultValue);//like this
Try to handle click event into adapter using interface like below
for example make one interface into adapter class ..
private onItemClick onItemClick;
public void setOnItemClick(DisplayAllData.onItemClick onItemClick) {
this.onItemClick = onItemClick;
}
public interface onItemClick{
void onItemSelected(int position); // pass your data
}
In getView() method like number listner called all logical code into activity or fragment.
holder.mTvName.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onItemClick.onItemSelected(position);
}
});
In activity or fragment after adapter set into listview or recyclerview then
adapter not null then called below code..
allDataAdapter.setOnItemClick(new DisplayAllData.onItemClick() {
#Override
public void onItemSelected(int position) {
// here called all logical part
allDataAdapter.notifyDataSetChanged();
}
});
I'm getting a variable data sent from activity to my adapter by using
sendData method, but every time when I try to access it in my getView method it resets to 0, please help. I've tried to debug code to check if the data from an activity is passing and it looks ok. I also created a getNumb method but still, the variable resets to 0. Here is my adapter code:
public class WorkoutListAdapterTwo extends BaseAdapter {
private int y;
public WorkoutListAdapterTwo() {
}
public int sendData(int x){
this.y = x;
return y;
}
public int getNumb(){
return this.y;
}
private static LayoutInflater mLayoutInflater = null;
public WorkoutListAdapterTwo(Activity ctx) {
this.mLayoutInflater = ctx.getLayoutInflater();
}
#Override
public int getCount() {
return WorkoutContentTwo.WORKOUTSTWO.size();
}
#Override
public Object getItem(int position) {
return WorkoutContentTwo.WORKOUTSTWO.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
int j = getNumb();
WorkoutTwo workout = (WorkoutTwo) getItem(j);
String [] arrOfStrings = workout.name.split(",");
if (convertView == null) {
convertView = mLayoutInflater.inflate(R.layout.adapter_workout_row, parent, false);
holder = new ViewHolder();
holder.id = (TextView) convertView.findViewById(R.id.workout_id);
holder.name = (TextView) convertView.findViewById(R.id.workout_name);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// Set the content for the ListView row
//holder.id.setText(workout.id);
//holder.name.setText(arrOfStrings[i]);
holder.id.setText(Integer.toString(position+1));
holder.name.setText(workout.ArrList[position]);
// Set the color for the ListView row
holder.id.setBackgroundColor(workout.dark);
holder.name.setBackgroundColor(workout.light);
return convertView;
}
Here I'm adding the code where I'm calling my method:
public void onItemSelected(int position) {
// Start the detail activity for the selected workout ID.
Intent detailIntent = new Intent(this, WorkoutDetailActivityTwo.class);
detailIntent.putExtra(WorkoutDetailFragmentTwo.ARG_WORKOUT_POS, position);
WorkoutListAdapterTwo newAdd = new WorkoutListAdapterTwo();
newAdd.sendData(position);
newAdd.notifyDataSetChanged();
startActivity(detailIntent);
}
Are you notifying your adapter to update views after updating the value? If your sendData() is not called until after the adapter has done it's first draw, you will need to call notifyDataSetChanged() so that the adapter knows there are new values that should be used to update your views.
You have to make a interface or you can a use notifyDataSetChanged depends on the use if you are doing search operation then use the notifyDataSetChanged method but if you want to send some data then
Fragment or activity
public class ExampleFragment extends Fragment implements MyAdapter.SuccessResponse{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View contentView = inflater.inflate(R.layout.my_layout, container, false);
MyAdapter myAdapter = new MyAdapter(getActivity(), 0);
myAdapter.successResponse = this;
return contentView;
}
#Override
public void onSuccess() {
}
}
The adapter code
class MyAdapter extends ArrayAdapter{
SuccessResponse successResponse;
public MyAdapter(Context context, int resource) {
super(context, resource);
}
public interface SuccessResponse{
void onSuccess();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//ur views
linearLayout.setOnClickListener(new View.OnClickListener{
#Override
public void onClick (View view){
if(successResponse!=null)
successResponse.onSuccess();
}
})
}
}
You can use any type of adapter i am use arrayadaper here.
I'm trying to implement an Android app for sudoku game, and i created a customized adapter for that. i want make edit text for cells the user is allowed to modify, and textview for cell filled by the program, the number of ediTexts and textViews will be random. how do specify that in the adapter ?
This is my adapter :
public class SodukuAdapter extends BaseAdapter {
ArrayList<String> items;
static Activity mActivity;
private static LayoutInflater inflater = null;
public SodukuAdapter (Activity activity, ArrayList<String> tempTitle,) {
mActivity = activity;
items = tempTitle;
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public final int getCount() {
return items.size();
}
#Override
public final Object getItem(int position) {
return items.get(position);
}
#Override
public final long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = null;
v = inflater.inflate(R.layout.item, null);
EditText et = (EditText) v.findViewById(R.id.et);
et.setText(items.get(position));
return v;
}
}
You can place both views in the same parent (e. g. parent is a RelativeLayout or a FrameLayout) so they are on top of each other. Than you simply hide one of them and show the other using setVisibility() in your getView() method of the adapter.
Of course you would need a datasource object which keeps track of whether a view should show the TextView or the EditText:
class SodokuItem {
public boolean isStatic;
public String text;
}
...
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = inflater.inflate(R.layout.item, null);
SodokuItem item = items.get(position);
EditText et = (EditText) v.findViewById(R.id.et);
TextView tv = (TextView) v.findViewById(R.id.tv);
if(item.isStatic){
et.setVisibility(GONE);
tv.setText(item.text);
}else{
tv.setVisibility(GONE);
et.setText(item.text);
}
return v;
}
I've been working on creating a single choice ListView populated by a custom ArrayAdapter (which works), except I need to set a pre-determined RadioButton in the ListView as setChecked(true) when the activity launches.
I'm populating my ListView with a List<Server> servers object at inflation that contains a boolean 'default_server' used to determine which row / RadioButton should be setChecked(true).
Selecting the various ListView items after the activity has launched correctly flags the specific RadioButton as setChecked(true) in Single Choice mode as desired.
My code:
ServerActivity.java
public class ServersActivity extends FragmentActivity
//FragmentActivity needed to display dialog fragment when ListView item clicked
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.server_list);
servers = getServers();
lv = (ListView) findViewById(android.R.id.list);
lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
adapter = new ServerActivityArrayAdapter(this, R.layout.server_list_item, servers);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// show dialog if not long clicked
if (!longClicked) {
lv.setItemChecked(position, true);
showServerDialog(position);
}
}
});
}
ServerActivityArrayAdapter.java
public class ServerActivityArrayAdapter extends ArrayAdapter<Server> {
private int layout;
private int mSelectedPosition = -1;
private RadioButton mSelectedRB;
private static LayoutInflater inflater;
public ServerActivityArrayAdapter(Context context, int layout, List<Server> servers) {
super(context, layout, servers);
ListArrays listArrays = new ListArrays(context);
this.layout = layout;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
private static class ServerViewHolder {
private TextView textView;
private RadioButton radioButton;
public ServerViewHolder() {
// EMPTY DEFAULT CONSTRUCTOR
}
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final Server server = this.getItem(position);
final ServerViewHolder viewHolder;
if (convertView == null) {
convertView = inflater.inflate(layout, parent, false);
viewHolder = new ServerViewHolder();
viewHolder.textView = (TextView) convertView.findViewById(R.id.tvServerName);
viewHolder.radioButton = (RadioButton) convertView.findViewById(R.id.rbDefault);
convertView.setTag(viewHolder);
} else {
viewHolder = (ServerViewHolder) convertView.getTag();
}
// TODO: SET THE DEFAULT SERVER
viewHolder.radioButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (position != mSelectedPosition && mSelectedRB != null) {
mSelectedRB.setChecked(false);
}
mSelectedPosition = position;
notifyDataSetChanged();
mSelectedRB = (RadioButton) v;
server.setDefaultServer(mSelectedRB.isChecked());
}
});
if (mSelectedPosition != position) {
viewHolder.radioButton.setChecked(false);
} else {
viewHolder.radioButton.setChecked(true);
if (mSelectedRB != null && viewHolder.radioButton != mSelectedRB) {
mSelectedRB = viewHolder.radioButton;
}
}
viewHolder.textView.setText(server.getName());
return convertView;
}
}
Again, my List<Server> servers object is populating the ListView, the subsequent dialog popups (when a row is clicked) correctly and the RadioButtons on each row are currently functioning in Single Choice mode. I'm using server.setDefaultServer(mSelectedRB.isChecked()); in the setOnClickListener of ServerActivityArrayAdapter to update which server has default_server(true).
Everything I've tried so far in the ServerActivityArrayAdapter seems to break the Single Choice mode requirement of the RadioButton. How can I fix this?
I did go back and implement Shared Preferences into my project as Mridul suggested, but the solution really didn't require them.
Basically, I updated the constructor of my ServerActivityArrayAdapter class to let me pass the ID of the default server from the ServerActivity class when it's created. Also, I set mSelectionPostion = defServer, so the correct RadioButton in my ListView is checked when everything is inflated.
public ServerActivityArrayAdapter(Context context, int layout, List<Server> servers, int defServer) {
super(context, layout, servers);
ListArrays listArrays = new ListArrays(context);
this.layout = layout;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mSelectedPosition = defServer;
}
Android not parsing JSON data into ListView, I am using this tutorial and just made few changes in ListViewAdapter.java
Like in my new implementation i used ViewHolder, and my code looks like this:
public class ListViewAdapter extends BaseAdapter {
// Declare Variables
Context context;
ArrayList<HashMap<String, String>> data;
ImageLoader imageLoader;
HashMap<String, String> resultp = new HashMap<String, String>();
ViewHolder holder;
public ListViewAdapter(Context context,
ArrayList<HashMap<String, String>> arraylist) {
this.context = context;
data = arraylist;
imageLoader = new ImageLoader(context);
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
static class ViewHolder {
public ViewHolder(View convertView) {
// TODO Auto-generated constructor stub
}
TextView rank;
TextView country;
TextView population;
ImageView flag;
}
public View getView(final int position, View convertView, ViewGroup parent) {
// Declare Variables
// Avoid unneccessary calls to findViewById() on each row, which is expensive!
holder = null;
/*
* If convertView is not null, we can reuse it directly, no inflation required!
* We only inflate a new View when the convertView is null.
*/
if (convertView == null) {
convertView = ((Activity) context).getLayoutInflater().inflate(R.layout.listview_item, null);
// Create a ViewHolder and store references to the two children views
holder = new ViewHolder(convertView);
holder.rank = (TextView) convertView.findViewById(R.id.rank);
holder.country = (TextView) convertView.findViewById(R.id.country);
holder.population = (TextView) convertView.findViewById(R.id.population);
// Locate the ImageView in listview_item.xml
holder.flag = (ImageView) convertView.findViewById(R.id.flag);
// The tag can be any Object, this just happens to be the ViewHolder
convertView.setTag(holder);
} else {
// Get the ViewHolder back to get fast access to the TextView
// and the ImageView.
holder = (ViewHolder) convertView.getTag();
}
// Capture position and set results to the TextViews
holder.rank.setText(resultp.get(MainActivity.RANK));
holder.country.setText(resultp.get(MainActivity.COUNTRY));
holder.population.setText(resultp.get(MainActivity.POPULATION));
// Capture position and set results to the ImageView
// Passes flag images URL into ImageLoader.class
imageLoader.DisplayImage(resultp.get(MainActivity.FLAG), holder.flag);
// Capture ListView item click
return convertView;
}
}
Edited: Click on ListItem code
#Override
protected void onPostExecute(Void args) {
// Locate the listview in listview_main.xml
listview = (ListView) findViewById(R.id.listview);
// Pass the results into ListViewAdapter.java
adapter = new ListViewAdapter(MainActivity.this, arraylist);
// Set the adapter to the ListView
listview.setAdapter(adapter);
// Close the progressdialog
mProgressDialog.dismiss();
listview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// code to handle click
}
});
}
But i don't no why i am not getting data into ListView !
The issue is that you are not assigning the HashMap to `resultp that has the information you want to display
public View getView(final int position, View convertView, ViewGroup parent) {
holder = null;
if (convertView == null) {
convertView = ((Activity) context).getLayoutInflater().inflate(R.layout.listview_item, null);
holder = new ViewHolder(convertView);
holder.rank = (TextView) convertView.findViewById(R.id.rank);
holder.country = (TextView) convertView.findViewById(R.id.country);
holder.population = (TextView) convertView.findViewById(R.id.population);
holder.flag = (ImageView) convertView.findViewById(R.id.flag);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// Here's the change
resultp = data.get(position);
// Here's the change
holder.rank.setText(resultp.get(MainActivity.RANK));
holder.country.setText(resultp.get(MainActivity.COUNTRY));
holder.population.setText(resultp.get(MainActivity.POPULATION));
imageLoader.DisplayImage(resultp.get(MainActivity.FLAG), holder.flag);
return convertView;
}
To attach OnItemClickListener to your ListView, in the Activity that contains the ListView, add the following:
public class MyActivity implements OnItemClickListener{
ListView lv;
#Override
public void onCreate(Bundle savedInstanceState() {
....
....
// lv initialized here
// adapter of lv set here
attachListeners();
}
private void attachListeners() {
....
....
// attach listeners to other views if you like
lv.setOnItemClickListener(this);
}
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// code to handle click
}
}
Or, if you don't want your Activity to implement OnItemClickListener, then,
public class MyActivity {
ListView lv;
#Override
public void onCreate(Bundle savedInstanceState() {
....
....
// lv initialized here
// adapter of lv set here
attachListeners();
}
private void attachListeners() {
....
....
// attach listeners to other views if you like
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// code to handle click
}
});
}
}
First of all try to fix this:
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}