Wrong position of items after using a customAdapter - java

This is the tutorial I have used: http://www.tutorialsbuzz.com/2014/08/filter-custom-listviewbaseadapter.html
and I implemented to it an onItemClickListener
OnItemClickListener myListViewClicked = new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String member_name = countrylist.get(position).getName();
// get Internet status
isInternetPresent = cd.isConnectingToInternet();
if (isInternetPresent) {
if (member_name.equals("aa")) {
Intent i = new Intent(Listview.this, Start.class);
startActivity(i);
displayInterstitial();
} else {
prName.show();
}
}
};
lv.setOnItemClickListener(myListViewClicked);
}
so, let us suppose my original list is
Aa
BB
Ca
DD
and I type 'a' in the filter, then the list becomes
Aa
Ca
But when I click Ca, I get redirected into BB using further action that depends on .equal for each list item.
My code for my list and custom adapter is the same as in the tutrial, but the onclickitem listener, i have implemeneted it, so I think im missing something in it. I tried searching and found couple of same quesiton, but none answered, each with self-answer that was different than mine and i couldn't apply it to my cusotm adapter.

it is mostly because your are accessing the dataset directly.
String member_name = countrylist.get(position).getName();
During the filtering you are probably instantiating and new Collection overriding the the reference you are using in your Activity.
Use
String member_name = ((Country)parent.getItemAtPosition(position)).getName();
and it will work.
parent.getItemAtPosition(position) accesses the underlying dataset in your Adapter, if your getItem is correctly implemented

You can use
String memberName=(YourObject)parent.getAdapter().get(postion).getName;
its easy.

Related

Trying to explain a Java method in Android Studio with Intent

I'm trying to do a written report on some code and I found one on youtube. However I don't understand what is going on exactly. I understand that it get's the ID of a certain object which then opens in a new Java class but if someone could breakdown what is happening it would be greatly appreciated.
private void setUpOnclickListener()
{
listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l)
{
Supplier selectSupplier = (Supplier) (listView.getItemAtPosition(position));
Intent showDetail = new Intent(getApplicationContext(), DetailActivity.class);
showDetail.putExtra("id",selectSupplier.getId());
startActivity(showDetail);
}
});
}
at first read some doc, what IS an Activity, then read how to start new one, and why Intent is needed for this
in short: this Intent is carrying information what dev want to start/open (will start new "window" - DetailActivity) and what will be passed to this component (some id)
The code gets the supplier that is clicked on in the listview in order to gain their supplier id. That ID is then given to the DetailActivity page using an intent, whereby it will be used to display the details that relate to the specific supplier. On the DetailActivity page, the intent and its extra information, namely the supplier id, will be retrieved, and then can be used to display the details for the specific supplier that was clicked on on the previous page.

How to retrieve the position in a ListView with Firebase results

I'm not using FirebaseAdapter or any Firebase-UI dependency, I have made this completly native for now, but I'm getting a problem at this line trying to pass extras:
mRootDatabase = getAdapter(mContext).getItem(position);
Required DatabaseReference , Found UserPojo
public void clickListItems(ListView listView,final DatabaseReference mRootDatabase) {
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
Toast.makeText(mContext, "Clicked: " + getmList().get(position), Toast.LENGTH_SHORT).show();
mRootDatabase = getAdapter(mContext).getItem(position);
Intent intent = new Intent(mContext, UserEdit.class);
intent.putExtra("uid", mRootDatabase.getKey());
intent.putExtra("Name",getAdapter(mContext).getItem(position).getName());
intent.putExtra("Email", getAdapter(mContext).getItem(position).getEmail());
intent.putExtra("Pay", getAdapter(mContext).getItem(position).getPay());
intent.putExtra("LastCon", getAdapter(mContext).getItem(position).getLastCon());
intent.putExtra("FirstCon", getAdapter(mContext).getItem(position).getFirstCon());
mContext.startActivity(intent);
}
});
}
In FirebaseListAdapter you can use getRef() in order to do this faster, but im wondering how to approach the same without it because my app does not have implemented any FirebaseAdapters , and I dont want to redo all my code again
Edit:
This is how I got my adapter
public ArrayAdapter<UserPojo> getAdapter(Context adapterContext) {
return new ArrayAdapter<UserPojo>(adapterContext,android.R.layout.simple_list_item_1,getmList());
}
Thanks!
To solve this, you need to change the following line of code:
mRootDatabase = getAdapter(mContext).getItem(position);
to
mRootDatabase = adapter.getRef(position);
In which adapter variable is the actual adapter that you are using to display the data.
Edit:
You cannot use getRef() method, unless you are using Firebase-UI library. You cannot get the DatabaseReference object from the ArrayAdapter object. None of the methods inside this class return a DatabaseReference object. The only way in which you can achieve this is to use Firebase-UI library.
It looks like you're trying to assign a Pojo to a Database Reference, instead you would need to assign it to the actual pojo and reference it that way
Something like this
UserPojo User = adapter.getItem(position);

Editing and saving an ArrayList<> that has been passed to another activity

I am making a frisbee logger and have an ArrayList of Team objects. Each Team has an ArrayList of Player objects. Everything is using Serializable properly to be sent using Intent.
In my main activity I am displaying the list of Team objects in a ListView and an option to add another Team (only a name is needed). Once a Team is selected I pass the object to another activity using Intent. On this second activity I have it display the list of Player objects and have fields to enter another player object into the passed list.
When I return to the main activity and go back to the add Player activity, what I have added is gone.
I cannot use static because there is obviously more than one Team object. I think passing back the changed ArrayList could work but that seems a little lame, time-consuming, and frustrating.
Is there a built-in way in Android Studio that does this or am I on my own?
Note: I am not using SQLite as suggested in the comments
There's not a whole lot to show on this but here it is I guess:
MainActivity.java
private static ArrayList<Team> listOfTeams = new ArrayList<>();
private static ArrayList<Game> listOfGames = new ArrayList<>();
private ListView gameList, teamList;
.....
teamList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Team t = (Team)teamList.getItemAtPosition(position);
viewTeam(t);
}
});
.....
//Item select in teamList. Start the TeamViewActivity
public void viewTeam(Team t)
{
Intent i = new Intent(this, TeamViewActivity.class);
i.putExtra("teamView",t);
startActivity(i);
}
TeamViewActivity.java
private Team team;
private ListView rosterList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_team_view);
rosterList = (ListView) findViewById(R.id.playerList);
Intent i = getIntent();
Bundle extras = i.getExtras();
if(extras!=null)
{
if(extras.get("teamView")!=null)
{
team = (Team) extras.get("teamView");
}
}
populateRosterList(team.getRoster());
}
public void addPlayerToRoster(View view)
{
String checkFirst = ((EditText) findViewById(R.id.firstText)).getText().toString();
String checkLast = ((EditText) findViewById(R.id.lastText)).getText().toString();
String checkNumber = ((EditText) findViewById(R.id.numberText)).getText().toString();
if(!checkNumber.equals(""))
{
team.addPlayer(checkFirst, checkLast, Integer.parseInt(checkNumber));
((EditText) findViewById(R.id.firstText)).setText("");
((EditText) findViewById(R.id.lastText)).setText("");
((EditText) findViewById(R.id.numberText)).setText("");
populateRosterList(team.getRoster());
}
}
public void returnToMain(View view)
{
Intent i = new Intent(this, MainActivity.class);
i.putExtra("teamView", team);
startActivity(i);
}
private void populateRosterList(ArrayList<Player> list)
{
ArrayAdapter<Player> adapter = new ArrayAdapter<>(this,
R.layout.activity_list, R.id.genericText, list);
rosterList.setAdapter(adapter);
}
Consider your concept:
You serialize an object, i.e. you transform it into a transferrable format which is then copied over to the other activity and reconstructed as a new instance.
Consequently, you alter another instance, which is not available in the previous activity, if you do not return it - again, serialized - and finally reconstruct and copy it back into the respective instance.
What you need is a shared memory storage in your application, which can alter and retrieve data cross-activity OR a proper data routing using Intents w/ ISerializable.
Options:
Always serialize objects and pass and copy them around.
-> No multithreaded alteration, possibly slow, unbeautiful
Singleton application with global data storage ir Context Object (I do NOT recommend the due to memory management and Garbage
Collection inbetween Activity Switches BUT for consistency I'd
wanted to mention this option)
SQLite3
-> Quick, Simple and Scalable, But a bit cumbersome to get started with
Any other file-structure stored and maintained in the data folder
-> I'd expect a lot of boilerplate code here, and low performance
Webservice and remote database
Proper component setup, i.e. initialize all accessing components in your software with the appropriate reference to the data structs using for example fragments (Thanks to #mismanc, I actually missed that option initially)
In general you could abstract all that away using services and repositories, which allows you to under-the-hood test options like 3. 4. And 5. and find your best solution, and in addition, keeo the accessing code simple and clean.
in your case, you can use startActivityForResult instead of startActivity, then get your modified Team object from onActivityResult(int requestCode, int resultCode, Intent data) to update your list.
startActivityForResult example
You can use fragments. You hold the list in the MainActivity and pass its reference to ShowListFragment and AddPlayerFragment by interfaces. And you can also do other operations over them. If you dont want to use json or sqlite it can be a good way for you.
MainActivity.java
public class MainActivity extends Activity implements ShowListener{
public interface ShowListener{
ArrayList<Team> getTeamList();
}
private ArrayList<Team> listOfTeams = new ArrayList<>();
#Override
public ArrayList<Team> getTeamList() {
return listOfTeams;
}
}
ShowListFragment.java
public class ShowListFragment extends Fragment {
private ArrayList<Team> listOfTeams;
private ShowListener listener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
listener = (ShowListener)getActivity();
listOfTeams = listener.getTeamList();
}
}
As #Kingfisher Phuoc mentioned you could use srartActivityForResult in case you don't want to change your approach.
Otherwise I will suggest you use either :
SharedPreference to store your arraylist object (by converting the arraylist to json then store it as string in json format). In the PlayerActivity you retrieve the data, manipulate it then save it. see this post
SQLite

JUnit test on android app with cache and ArrayAdapter

// use case 10b alternate version
// caches a read comment temporarily
public void testCacheReadComment2() throws Throwable{
runTestOnUiThread(new Runnable()
{
#Override
public void run(){
CommentBuilder commentBuilder = new commentBuilder();
Comment comment = commentBuilder.createTopTestComment();
//browse button on main screen
((Button)activity.findViewById(ca.ualberta.cs.team5geotopics.browseButton)).performClick();
//the ListView for the custom adapter
ListView listView = (ListView) activity.findViewById(ca.ualberta.cs.team5geotopics.commentList);
//the custom adapter on the physical screen
ArrayAdapter<Comment> adapter = (ArrayAdapter<Comment>) listView.getAdapter();
adapter.add(comment);
adapter.notifyDataSetChanged();
View view = adapter.getView(adapter.getPosition(comment), null, null);
ViewAsserts.assertOnScreen(listView, view);
//this is the button to view the Top Level comment in the list
ViewAsserts.assertOnScreen(view, (Button) view.viewTopLevelComment);
((Button)view.viewTopLevelComment).performClick();
// is there a way I can get references to the objects
// already instantiated in the test thread?
CacheController cc = activity.getCacheController();
assertTrue(cc.getHistory().contains(comment));
}
});
}
We are using a test driven development style in order to code our project for school. In this test I am trying to prove that after a user views a comment from the list in the adapter, that this comment is cached in a history cache. I'm a little confused about some things and I would like some help, because it would be great if I knew there were no obvious flaws in my test case. these are my questions:
View view = adapter.getView(adapter.getPosition(comment), null, null);
Will this line return the view that is associated with the comment stored in the array adapter? My ArrayAdapter is going to follow a holder patter and I'm not sure if this is the proper way to get access to the buttons I need to mimic the user viewing the comment.
CacheController cc = activity.getCacheController();
I have a CacheController object that is instantiated upon the onCreate() method in our main activity. Now I want to reference this CacheController to see if the history is updated properly. I was just making a new CacheController and mimicking the actions of the CacheController in the test method, but I want to test what happens to my data on the UIthread. So, how do I reference objects in the UI thread?
View view = adapter.getView(adapter.getPosition(comment), null, null);
Will this line return the view that is associated with the comment
stored in the array adapter?
I think it should work, but I don't understand why would you want to access the View.
My ArrayAdapter is going to follow a holder patter and I'm not sure if
this is the proper way to get access to the buttons I need to mimic
the user viewing the comment.
The ArrayAdapter is usually used for a ListView. You should just let ListView handle the click capturing and tell you which element was clicked.
So, how do I reference objects in the UI thread?
You have 2 solutions for this that come to my mind right now:
1) Pass the CacheController instance, for example:
public class YourClass {
private final CacheController cacheController;
public YourClass(final CacheController cacheController) {
this.cacheController = cacheController;
}
public void testCacheReadComment2() throws Throwable {
CacheController cc = this.cacheController;
}
}
2) Singleton: make the CacheController static and put an accessor, for example:
public class CacheController {
private final CacheController instance = new CacheController();
public static CacheController getCacheController() {
return instance;
}
}
In both cases you should be aware about potential multi-threading issues because you're spawning new threads that all share same CacheController instance.

How to link classes and menus

I am really struggling with linking menus together. The app I want to create os a collection of menus that leads to url links to various sites I plan to open within the application. I have created a list activity menu with 8 options and I have eight classes with further options. My problem is how to link the menus together.
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Create an array of Strings, that will be put to our ListActivity
String[] names = new String[] { "P", "Ch", "Le", "Le", "B", "Sk", "Awa", "Tra"};
// Create an ArrayAdapter, that will actually make the Strings above
// appear in the ListView
this.setListAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_checked, names));
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
// Get the item that was clicked
Object o = this.getListAdapter().getItem(position);
String keyword = o.toString();
Toast.makeText(this, "You selected: " + keyword, Toast.LENGTH_LONG)
.show();
}
}
At the moment all this does is print the selection using the toast method but how do I get it to switch to the p.java class when I have selected it. In basic I would take the names variable and say if names = p goto p.java, I have googled and although I get part of the answer I cannot figure out how to implement it.
Many Thanks In Advance.
I suspect that rather than a class, what you want is an instance of the class in question. One way to do that would be with a Map:
Map<String, Runner> runners = new HashMap<String, Runner>();
runners.put("P", new P());
runners.put("Ch", new Ch());
// etc.
(where Runner is an interface that all your classes implement). Then, inside your onListItemClick() method, where you have the toast:
runners.get(keyword).run();
(where run() is the method you want to launch).
Update (to address your comment)
It's hard to say exactly where to place which bits of code, but based on your question:
You could make runners a field in your Activity, and initialize it in your same onCreate function. So that part's handled.
The Runner interface could be as simple as this (in its own file):
public interface Runner {
public void run();
}
and each of your classes (P, Ch, Le, etc.) would have an implements bit in the constructor:
public class P implements Runner {
And would have to include a run() method (which could simply call whatever existing method you want called for the URL):
public void run() {
// do whatever you want done here
}

Categories