ListView add items two times in onCreate - android

In my MasterDetail Flow I call this function to create my list:
public class Ansicht extends SherlockFragmentActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
//...
ListItems.setupMainItems(this);
//...
}
}
public class ListItems
{
public static List<DetailListItem> ITEMS = new ArrayList<DetailListItem>();
public static Map<String, DetailListItem> ITEM_MAP = new HashMap<String, DetailListItem>();
public static void addItem(String value, Typ t)
{
DetailListItem item = new DetailListItem(value, t);
ITEMS.add(item);
ITEM_MAP.put(item.id, item);
}
//...
}
public class ListControl extends SherlockListFragment
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
adapter = new ArrayAdapter<ListItems.DetailListItem>(getSherlockActivity(), R.layout.simple_listitem, android.R.id.text1,ListItems.ITEMS);
setListAdapter(adapter);
}
//...
}
But if I close my app and start it again the items are insert a second time. I think I do not have to call this function in onCreate but this image does not really help me because onCreate is the first method with is called.
In my setupMainItems method I only call the addItem method. The onPause and onResume are never overriden. If I close my app with the homebutton all works great but if I close it with the back button the items are insert a second time.

You could do something like
if(ListItems.ITEMS == null || ListItems.ITEMS.size() == 0)
ListItems.setupMainItems(this);
That way it'll only add the items if they haven't been added already

Related

Does Android save and restore instance state of some field automatically?

I have a RecyclerView with MyItem as holding the data for each rows in the RecyclerView, and everything is properly implemented and working fine.
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder>{
protected final List<MyItem> items= new ArrayList<>();
public MyAdapter (List<RVItem> list) {
if (list != null) {
items.addAll(list);
}
}
}
And the List items is passed from another object.
public class MyObject{
private String otherThing;
private List<MyItem> items;
public someMethodToInitItems() {
items = new ArrayList<>();
items.add(...);
items.add(...);
}
public createFragment() {
Fragment f = new MyCustomFragment();
f.setAdapter(new MyAdapter(items));
// replace commit fragment...
}
}
The problem here is when my Activity is restored, the field private List<MyItem> items in MyObject somehow magically get restored too, but field like otherThing is still null and not getting restored.
FYI, I did not explicitly save and restore items in any way. Also, onSaveInstanceState in MyCustomFragment is left untouched and not overridden from super.
Below is how I'm trying to save and restore the Fragment state from the Activity. That's it.
public class MyActivity{
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
getSupportFragmentManager().putFragment(outState, tag, getLastFragment());
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null) {
Fragment fg = getSupportFragmentManager().getFragment(savedInstanceState, tag);
}
}
}
So, I don't get it. Is Android system did this job? Save and restore the field items in MyObject automatically? Or there must be something else causing this behavior.
You need to override onRetainNonConfigurationInstance method. This method could helps you to store your data
More details here

I can't figure out why my adapter is not updating my recyclerview

I have read some similar questions and and i have tried to get it work but i can't understand why my adapter is not updating my recyclerview after return from my SaveItem activity. So i have two tabs: ALL notes and Favourite notes. To be more specific: App image
.
When i press the floating action button from the bottom it starts a new activity where i can record a new note, but when i return to MainActivity the first fragment it's not updating my recyclerview:
Here is where I fill my adapter:
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
adapter = new NoteAdapter(fillAdapter(),this,getActivity());
recycler.setAdapter(adapter);
recycler.setLayoutManager(new LinearLayoutManager(getActivity(),LinearLayoutManager.VERTICAL,false));
}
Here is where I try to update my recyclerview:
#Override
public void onResume() {
super.onResume();
adapter.addAll(fillAdapter());
recycler.setAdapter(adapter);
}
Here is my addAll method:
public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.ViewHolderNote> {
// Other codes....
public void addAll(List<Note> newNotes) {
this.notes.clear();
this.notes.addAll(newNotes);
this.notifyDataSetChanged();
}
}
Take a list of Note in your Fragment class.
private List<Note> allNotes;
Then inside your onActivityCreated
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
allNotes = fillAdapter();
adapter = new NoteAdapter(allNotes, this, getActivity());
recycler.setAdapter(adapter);
recycler.setLayoutManager(new LinearLayoutManager(getActivity(),LinearLayoutManager.VERTICAL,false));
}
Now to update your list call the fillAdapter function again to popuate the allNotes list again and modify your onResume like this.
#Override
public void onResume() {
super.onResume();
allNotes = fillAdapter();
adapter.notifyDatasetChanged();
}
The addAll function has no necessity right now. Remove the function from your NoteAdapter.
The key thing is the reference of your list which is being passed to the adapter.

How to use notifyDataSetChanged with finish()

I have a list view which show list of task, on selecting task it shows details about task, when I delete the particular task it returns to the previous activity by finish(). but it does not update the list.
I want to know how and where to use notifyDataSetChanged method and add adapter method is never used.
Other than notifyDataSetChanged() solution is also accepted :) i just want to update the list when it returns to the previous activity.
Do it with startActivityForResult(). When you create intent to open new activity open it for result. The task being deleted is your result. So when it's marked as deleted and you return to your previous activity, the result triggers and you can delete the marked item + call the notify.
More info here : http://developer.android.com/training/basics/intents/result.html
you can use the notifyDataSetChanged on the onResume method, this always update the data itself when the Activity shows
You can also notify your parent activity before finishing your current activity. You just have to register a Receiver in your main activity and all others activities will be able to notify that activity. You can even send data!
As my english is not that good, sample code :
The MainActivity class
public class MainActivity extends AppCompatActivity {
// you can define your name for your receiver as a constant,
// so you can access it from other activities if you want
public static final String MY_SUPER_INTERNAL_NOTIFICATION = "MY_SUPER_INTERNAL_NOTIFICATION";
public static final String MY_OBJECT = "my_object";
public static final String MY_OBJECT_POSITION = "my_object_position" ;
private MyCustomAdapter adapter;
private ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView)findViewById(R.id.listView);
// set up your list with your adapter and data...
adapter = new MyCustomAdapter(this);
// [...] I suppose you know how to do that, I dont write everything
listView.setAdapter(adapter);
// when you click on a row from your list,
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(
MainActivity.this,
SecondActivity.class
);
// you can for example put data in a Bundle and pass it to the other activity
// then on the onCreate you can use that data as you want
Bundle bundle = new Bundle();
// IMPORTANT be sure that the object you are putting in the bundle is Serializable (implements Serializable)
bundle.putSerializable(MY_OBJECT, adapter.getItem(position));
// you can also for example send the position of the row you clicked
bundle.putInt(MY_OBJECT_POSITION, position);
// put your bundle in the intent
intent.putExtras(bundle);
startActivity(intent);
}
});
// register your Receiver! don't forget to do that or you will never be notified
LocalBroadcastManager
.getInstance(this)
.registerReceiver(
broadcastReceiver,
new IntentFilter(MY_SUPER_INTERNAL_NOTIFICATION)
);
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
// get the position sent by the other activity
int position = intent
.getExtras()
.getInt(SecondActivity.MY_EXAMPLE_KEY);
adapter.deleteItem(position);
}
}
};
// adapter class...
private class MyCustomAdapter extends BaseAdapter {
ArrayList<MyObject> data;
public MyCustomAdapter(Context context) {
}
public void deleteItem(int position){
// delete your item from the list of data
data.remove(position);
// dont forget to notify
notifyDataSetChanged();
}
#Override
public int getCount() {
return 0;
}
#Override
public MyObject getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return null;
}
// adapter class, you can extend your favorite type of adapter
}
}
The SecondActivity class :
public class SecondActivity extends AppCompatActivity {
public static final String MY_EXAMPLE_KEY = "EXAMPLE";
private MyObject myObject;
private int myObjectPosition;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_activity);
myObject = (MyObject) getIntent()
.getExtras()
.getSerializable(MainActivity.MY_OBJECT);
myObjectPosition = getIntent()
.getExtras()
.getInt(MainActivity.MY_OBJECT_POSITION);
// do all your stuff with your object
// before calling finish do this
beforeFinishDoThisStuff();
}
private void beforeFinishDoThisStuff() {
sendBroadcastToMainActivity();
finish();
}
private void sendBroadcastToMainActivity() {
// create an intent and put your Receiver name as action name
// like you defined in your MainActivity
Intent intent = new Intent(MainActivity.MY_SUPER_INTERNAL_NOTIFICATION);
Bundle bundle = new Bundle();
// put whatever you want, here I put just the previous position of the object in the list
bundle.putInt(MY_EXAMPLE_KEY, myObjectPosition);
intent.putExtras(bundle);
// notify your MainActivity
LocalBroadcastManager
.getInstance(this)
.sendBroadcast(intent);
// after this finish !
}
}
Hope you understand how to notify activities with BroadcastManager. It's very powerful and simple to use.
Have fun coding !

How to call an override method manually?Overrided method is not running

I have deveolped a method to call methods from another calss.I have created an adapter and inside that I have an override getView(). What I need to do is to get values from a listview and display as a report. I have tried this exact code inside another activity in the same project. It works perfectly. But when ever I moved this into another activity it doesn't give any error.But the overrided method is not calling. What should I do to make it run?
public class ViewList extends ActionBarActivity {
ArrayAdapter<Units> unitsAdapterView;
ListView ViewAll;
List<Units> Unit = new ArrayList<Units>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_list);
ViewAll = (ListView) findViewById(R.id.viewList);
populateListView();
viewView();
}
private void viewView(){
Button m=(Button)findViewById(R.id.tryBtn);
m.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// startActivity(new Intent(getApplicationContext(),ViewList.class));
populateListView();
}
});
}
private void populateListView(){
unitsAdapterView =new UnitListAdaptorView();
ViewAll.setAdapter(unitsAdapterView);
// unitsAdapterView.getView();
}
private class UnitListAdaptorView extends ArrayAdapter<Units> {
public UnitListAdaptorView() {
super (ViewList.this, R.layout.list,Unit);
Log.i("","A");
// A();
}
#override
public View getView(int position, View view, ViewGroup parent) {
Log.i("","Resue connceted bulb 5");
if (view == null) {
view = getLayoutInflater().inflate(R.layout.list,parent ,false);
}
Units currentUnit = Unit.get(position);
TextView name = (TextView)view.findViewById(R.id.lblViewName);
name.setText(currentUnit.getName());
TextView bulb=(TextView) view.findViewById(R.id.lblViewBulb);
bulb.setText(currentUnit.getBulbNo());
TextView fan=(TextView) view.findViewById(R.id.lblViewFan);
fan.setText(currentUnit.getFanNo());
return view;
}
}
}
The problem was solved after adding the codes to get all the existing data from database. After adding the below codes to the onCreate method the function is working now!
DatabaseHandler dbHandler = new DatabaseHandler(getApplicationContext());
if (dbHandler.getUnitsCount() != 0)
Unit.addAll(dbHandler.getAllUnit());

Can't start activity from class

I am trying to start an activity from a normal class and I can't figure out how it is done, if it can be done. On an itemClick I want to start an activity that extends the ListView class to show a list of options.
Also the class that receives the onItemClick is not an activity. I will post the code to try to visualize what i mean.
This is my onClick method in the class that wants to start a an activity.
public void onClick(View v) {
if (v.equals(this)) {
notifyObservers(this.getId());
} else if(v.equals(editButton) || v.equals(deleteButton)) {
This is where I want to start the activity to show my ListView...
}
}
This is my class that extends the ListView class.
public class ProfileSettings extends ListActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] mainSettings = getResources().getStringArray(R.array.mainSettings);
setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, mainSettings));
ListView lv = getListView();
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Do something
}
});
}
}
Thanks in advance!
I think this may help you:
"Pass the context of the activity via constructor to your class or make a static context in your activity.
With the context you can start activities like you would start them within the activity class."
class First extends Activity {
...
Second test = new Second(this);
test.start();
...
}
class Second {
private Context mContext;
...
public Second(Context c) { this.mContext = c; }
...
public start() { mContext.startActivity(...); }
}
for more detail check
http://www.anddev.org/view-layout-resource-problems-f27/starting-an-activity-from-a-non-activity-class-t14483.html
Try this in your onClick
Intent i = new Intent(this, ProfileSettings.class);
startActivity(i);
EDIT:
Also dont forget to add the activity to your manifest.

Categories

Resources