Java stack not working with Android adapter -
i'm developing file manager app amazon s3 in android. i'm using stack hold folder objects navigation. each object in stack folder holds arraylist mobjects of files , folders in folder.
an onclick event listener pushes clicked object onto stack , calls setter arraylist clicked object.
the problem subsequent objects pushed onto stack change mobjects field of first object in stack. don't understand why because mobjects field has modifier private each object.
many hours of code staring , google searches have turned blank. i've done stack trace in android studio , find weird mobjects field first object on stack changes @ line adapter.setdata(o.getmobjects()) in bucketobjectlistfragment class.
public class bucketobjectlistfragment extends listfragment { public static list<s3objectsummary> s3objlist; private final int position = 2; @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); generates3objects(); for(s3objectsummary s : s3objlist) { log.i("s3objlist", s.getkey()); } //create stack objectstack mystack = new objectstack(); //create new object hold home list view bucketobject o = new bucketobject(); o.setprefixkey("/"); //create home object's list of folders , files o.sethomeobjects(); //create adapter hold list of files , folders objectadapter adapter = new objectadapter(o.getmobjects()); setlistadapter(adapter); //replicate android onclick event. first push home view onto stack. mystack.push(o); log.i("stack dump", "..."); mystack.printstack(); //create new bucketobject clicked folder. o = ((objectadapter) getlistadapter()).getitem(position); o.setmobjects(o.getprefixkey()); adapter.setdata(o.getmobjects()); mystack.push(o); log.i("stack dump", "..."); mystack.printstack(); } public static void generates3objects(){ //generate random list of files , directories s3 objects. s3objlist = new arraylist<s3objectsummary>(); for(int i=0; i<5; i++){ s3objectsummary obj = new s3objectsummary(); s3objlist.add(obj); } } private class objectadapter extends arrayadapter<bucketobject> { private objectadapter(arraylist<bucketobject> objects) { super(getactivity(), android.r.layout.simple_list_item_1, objects); } public void setdata(arraylist<bucketobject> items) { clear(); setnotifyonchange(false); if (items != null) { (bucketobject item : items) add(item); } notifydatasetchanged(); } } } my bucketobject class.
public class bucketobject { private uuid id; private string prefixkey; private string key; private arraylist<bucketobject> mobjects; public bucketobject() { id = uuid.randomuuid(); } public bucketobject(string mprefixkey, string mkey) { id = uuid.randomuuid(); prefixkey = mprefixkey; key = mkey; } @override public string tostring() { return prefixkey; } public string getprefixkey() { return prefixkey; } public void setprefixkey(string mprefixkey) { prefixkey = mprefixkey; } public arraylist<bucketobject> getmobjects(){ return mobjects; } public arraylist<bucketobject> sethomeobjects(){ arraylist<bucketobject> mfiles = new arraylist<>(); mobjects = new arraylist<>(); //use hashset hold unique folders , directories set<string> myset = new hashset<string>(); (s3objectsummary summary : bucketobjectlistfragment.s3objlist) { string obj = summary.getkey(); int firstslash = obj.indexof("/"); if (firstslash != -1){ //if object has multiple forward slashes string mykey = obj.substring(0, firstslash); if(myset.add(mykey)){ //add set if not duplicate directory bucketobject b = new bucketobject((mykey + "/"), mykey); mobjects.add(b); } } else { //get files bucketobject b = new bucketobject(obj, obj); mfiles.add(b); } } mobjects.addall(mfiles); return mobjects; } public arraylist<bucketobject> setmobjects(string prefixkey){ arraylist<bucketobject> mfiles = new arraylist<>(); mobjects = new arraylist<>(); //use hashset hold unique folders , directories set<string> myset = new hashset<string>(); (s3objectsummary summary : bucketobjectlistfragment.s3objlist) { string obj = summary.getkey(); if (obj.startswith(prefixkey)) { string suffix = obj.replacefirst(prefixkey, ""); int firstslash = suffix.indexof("/"); if (firstslash != -1) { string key = suffix.substring(0, firstslash); if (myset.add(key)) { //add set if not duplicate directory bucketobject b = new bucketobject(obj, key); mobjects.add(b); } } else{ if(!suffix.equals("")) { bucketobject b = new bucketobject(obj, suffix); mfiles.add(b); } } } } mobjects.addall(mfiles); return mobjects; } } my objectstack class.
public class objectstack { private stack<bucketobject> s3objectstack; public objectstack(){ s3objectstack = new stack<>(); } public void push(bucketobject o) { s3objectstack.push(o); } public void printstack(){ //prints contents of mobjects each bucketobject in stack. for(bucketobject o : s3objectstack){ int = 0; log.i("bucketobject ", o.tostring()); for(bucketobject b : o.getmobjects()){ log.i("mobjects " + integer.tostring(i), b.tostring()); i++; } } } } class generate s3 objects.
public class s3objectsummary { private final string key; private static final string abc = "abcdefghijklmnopqrstuvwxyz"; private static securerandom rnd = new securerandom(); public s3objectsummary(){ key = randomstring(7); } public string getkey(){ return key; } private string randomstring(int len){ stringbuilder sb = new stringbuilder(len); for(int = 0; < len; i++){ sb.append(abc.charat(rnd.nextint(abc.length()))); } sb.insert(3, '/'); return sb.tostring(); } } main activity class.
public class startactivity extends appcompatactivity { @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_start); } } the xml activity fragment.
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.constraintlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="ie.codemaker.test_panda.startactivity"> <fragment android:name="ie.codemaker.test_panda.bucketobjectlistfragment" android:id="@+id/foofragment" android:layout_width="match_parent" android:layout_height="match_parent" /> </android.support.constraint.constraintlayout> edit: i've edited above provide complete, minimal , verifiable program. has helped me narrow problem down setdata() method of adapter. if rename clicked object other o, first object on stack, first object's private field still changes @ setdata(). if needs manifest.xml run code can provide it.
the problem here was, else has pointed out in answer question, "a typical java error pointers" using android's arrayadapter: https://stackoverflow.com/a/14408492/3350944
in following line i'm passing array mobjects adapter:
objectadapter adapter = new objectadapter(o.getmobjects()); then, in line i'm passing new array mobjects adapter adapter still pointing first array:
adapter.setdata(p.getmobjects()); i solved problem new arraylist<> in class bucketobjectlistfragment passed adapter:
private arraylist<bucketobject> newarray; objectadapter adapter = new objectadapter(newarray); then when want update adapter, clear adapter's list , add items newarray mobjects:
viewlist.clear(); for(bucketobject obj : p.getmobjects()){ newarray.add(obj); } adapter.notifydatasetchanged();
Comments
Post a Comment