ListView, ArrayAdapter in Android - java

I need some help with my class
I have to make an asynchronous call to the method getTodaysTweets()
in TweetUtil to retrieve data.
POPULAR list of data you collected.
View dialog for the app work while the asynchronous call of
TweetUtil is in progress.
Class
public class MainActivity extends Activity{
private ListView listOfTweets;
private ArrayAdapter<String> tweetsAdapter;
protected void onCreate (Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listOfTweets = (ListView) findViewById(R.id.listOfTweets);
tweetsAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
listOfTweets.setAdapter(tweetsAdapter);
//To:DO Get list of tweets from TweetUtil and populate list
//Do this asynchronus
}
}
public class TweetUtil{
public static List<String> getTodaysTweets(){
List<String> tweets = new ArrayList<String>();
//...getting tweets from twitter.com
//...adding the result to my List<String> tweets
return tweets;
}
}

using AsyncTask class that's will save your day and below good tutorial for it .
AsyncTask class help you to make asynchronous calling from Database or remote server and it's manage all threads you work , so you can call your method in your custom AsyncTask class –
good source for it :
http://vogella.com/articles/AndroidBackgroundProcessing/article.html

Related

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

Android : Inform adapter that data-set has changed from a static method

I am working on an Android project in which I am trying to integrate PUSH service offered by Cometd framework.
Now, whenever a new message arrives for a Conversation, I would like to inform ChatMessagesActivity which contains the list of messages between the two users.
Now, when the other user sends a message to the Android app, I would like to update the view of the user. I tried doing that by calling notifyDataSetHasChanged() on the adapter, but because I was calling it outside of View thread, I am getting an error.
The method is static, because new messages are received in Conversation class, while the messages are going-on in ChatMessagesActivity class. For communication between both classes, I have created 2 static methods which act like a bi-directional bridge for sending & receiving messages.
I hope I was clear, if there are any doubts, kindly let me know.
ChatMessagesActivity.java :
public class ChatMessagesActivity extends ApplicationDrawerLoader {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat_messages);
chatList = (ListView)findViewById(R.id.chatList);
new getPrivateChatsForUser(this).execute();
}
// IN the method below, I receive information from another activity.
public static void recieveUpdatedMessage(String channelName, Map<String, Object> input){
Boolean found = Arrays.asList(channelName.split(" ")).contains("chat");
if(found){
int processedChannelName = Integer.valueOf(channelName.replace("/chat/",""));
if(processedChannelName == groupAccountId){
// Here i tried calling adapter.NotifyDataSetchanged();.. Didn't fly.
}
}
}
// Async method retrieving messages.
public class getPrivateChatsForUser extends AsyncTask<Void, Void, ResponseEntity<RestReplies[]>> {
ChatMessagesActivity chatMessagesActivity = null;
getPrivateChatsForUser(ChatMessagesActivity chatMessagesActivity) {
this.chatMessagesActivity = chatMessagesActivity;
}
#Override
protected ResponseEntity<RestReplies[]> doInBackground(Void... params) {
// network connection related stuff, not relevant to problem
}
#Override
protected void onPostExecute(ResponseEntity<RestReplies[]> responseEntity) {
super.onPostExecute(responseEntity);
RestReplies[] restRepliesArray = responseEntity.getBody();
Collections.addAll(restRepliesList, restRepliesArray);
ArrayList<HashMap<String, String>> chatMessagesHashMapList = new ArrayList<HashMap<String, String>>();
for (RestReplies restReplies : restRepliesList) {
HashMap<String, String> chatMap = new HashMap<>();
chatMap.put(chatText, restReplies.getReplyText());
chatMap.put(firstName, restReplies.getReplyingPersonName());
chatMap.put(chatImage, restReplies.getSenderImage());
chatMap.put(privateChannel,"/service/person/"+String.valueOf(conversationId));
chatMessagesHashMapList.add(chatMap);
}
chatList = (ListView) findViewById(R.id.chatList);
chatMessagesAdapter = new ChatMessagesAdapter(chatMessagesActivity, chatMessagesHashMapList);
chatList.setAdapter(chatMessagesAdapter);
chatList.scrollTo(0, chatList.getHeight());
}
}
So, how should I instruct that the data-set has been changed.. And how does the adapter knows where and how to get the data-set which has changed. Can anyone help me with this problem. Thanks a lot... :-)
Use broadcast receiver at your adapter and fire a local broadcast with android LocalBroadcast in your push service
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent)
{
if(intent.getAction().equals("MYREFRESH"))
{
notifiyDataSetChanged();
}
}
};
In your constructor in adapter register this reciever
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("MYREFRESH");
LocalBroadcastManager.getInstance(context).registerReceiver(broadReceiver, intentFilter);
In your push if you get a push notification trigger this
Intent intent = new Intent();
intent.putExtra(...) //send any data to your adapter
Intent.setAction("myaction");
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
The way to deal with this is using a broadcast or bus pattern. You can use some good bus libraries such as http://square.github.io/otto/ or a LocalBroadcast
This past answer from me shows how to use the LocalBroadcast system: Refreshing fragments in FragmentActivity after sync service runs

Creating a basic adapter for searchview that uses asynctask

So I'm making this student project Android app that I use to search movies online.
The problem I'm having is that even though there is tons of material to read, I don't quite comprehend how adapters for searchview results are supposed to be made. I know what kind of data the query returns, but I still don't know how to make an adapter for it.
I'm only at a beginner level in Java and Android programming, but this project really fired me up and I've been working on it day and night. If you have any tips (to improve my code) please do share them.
public class SearchActivity extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.searchactivity);
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
new doMySearch().execute(query);
}
}
private class doMySearch extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... params) {
String parameters = (params[0]);
JTomato jtomato = new JTomato("gibberish-cencored");
jtomato.setPage_limit(1);
List<Movie> movies = new ArrayList<Movie>();
String total = String.valueOf(jtomato.searchMovie(parameters, movies, 0));
return total;
}
#Override
protected void onPostExecute(String result) {
}
}
}
}
The data this search should return (if the search word were hulk) is as follows: [The Incredible Hulk, Hulk, HULK VS., Hulkamania Forever, Hulk Hogan's All-Time Champ, Hulk Hogan - The Missing Matches] and as many more to be found with that search word. I'm using a Java client for rotten tomatoes API that does most of the coding for me (http requests and json object parsing).
You should probably use the class ArrayAdapter.
You can convert the string you receive into an array of strings, and then create an ArrayAdapter with the list of strings. If you set that adapter as the activity's list adapter, it will show the names of the movies in the activity.

ArrayList inside ArrayList - android adapter?

So, I have Client class, which stores Category ArrayList (Client can have a couple of categories). Each category stores Expense ArrayList. So, every category can have a couple of expenses.
Here is the issue: I want to set adapter for one listView, in which we would print out all of the expenses. I know how to create adapter for one ArrayList, but if we have ArrayList inside ArrayList - then I am lost.
Any tips or tricks you might be able to share with me?
Use ExpandableListView with ExpandableListAdapter
You can use an adapter inside another adapter. I have used this approach in a dummy project. I put the following code as a starting point.
class Category{ List<Expense> expenseList; }
//this adapter will be used in Activity
class CategoryAdapter extends ArrayAdapter<Category>{
//your other adapter code here
ArrayAdapter<Expense> expenseAdtr =new ExpenseAdapter(context, category.getExpenseList());
expenseListView.setAdapter(expenseAdtr );
expenseListView.setOnClickListner(....);
}
//this adapter will be used inside CategoryAdapter
class ExpenseAdapter extends ArrayAdapter<Expense>{
//your adapter code here, should have no issue here
}
class MyActivity extends Activity{
//somewhere onCreate or .....
List<Category> categoryList;
ArrayAdapter<Category> categoryAdtr =new CategoryAdapter(context, categoryList);
expenseListView.setAdapter(categoryAdtr);
}

Android Array Adapter with ArrayList and ListView not updating when the arraylist is changed

I have an android app with a screen that comprises of a ListView, which I am using to display a list of devices. These devices are held in an array.
I am trying to use the ArrayAdapter to display what is in the array on the screen in a list.
It works when I first load the SetupActivity class, however, there is the facility to add a new device in the addDevice() method, which means the array holding the devices is updated.
I am using notifyDataSetChanged() which is supposed to update the list but it doesn't seem to work.
public class SetupActivity extends Activity
{
private ArrayList<Device> deviceList;
private ArrayAdapter<Device> arrayAdapter;
private ListView listView;
private DevicesAdapter devicesAdapter;
private Context context;
public void onCreate(Bundle savedInstanceState) //Method run when the activity is created
{
super.onCreate(savedInstanceState);
setContentView(R.layout.setup); //Set the layout
context = getApplicationContext(); //Get the screen
listView = (ListView)findViewById(R.id.listView);
deviceList = new ArrayList<Device>();
deviceList = populateDeviceList(); //Get all the devices into the list
arrayAdapter = new ArrayAdapter<Device>(this, android.R.layout.simple_list_item_1, deviceList);
listView.setAdapter(arrayAdapter);
}
protected void addDevice() //Add device Method (Simplified)
{
deviceList = createNewDeviceList(); //Add device to the list and returns an updated list
arrayAdapter.notifyDataSetChanged(); //Update the list
}
}
Can anyone see where I am going wrong?
For an ArrayAdapter, notifyDataSetChanged only works if you use the add, insert, remove, and clear functions on the Adapter.
Use clear to clear the adapter - arrayAdapter.clear()
Use Adapter.addAll and add the newly formed list - arrayAdapter.addAll(deviceList)
Call notifyDataSetChanged
Alternatives:
Repeat this step after new devicelist is formed - but this is
redundant
arrayAdapter = new ArrayAdapter<Device>(this, android.R.layout.simple_list_item_1, deviceList);
Create your own class derived from BaseAdapter and ListAdapter that
gives you more flexibility. This is most recommended.
While the accepted answer solves the problem, the explanation of why is incorrect, and since this is an important concept I thought I'd attempt to clarify.
Slartibartfast's explanation that notifyDataSetChanged() only works when add, insert,remove, or clear is called on the adapter is incorrect.
That explanation is true of the setNotifyOnChange() method, which if set to true (as it is by default) will automatically call notifyDataSetChanged() when any of those four actions occur.
I think the poster confused the two methods. notifyDatasetChanged() itself does not have those restrictions. It just tells the adapter that the list it is looking at has changed, and it does not matter how the change to the list actually happened.
While I can't see the source code for your createNewDeviceList(), I would guess your problem came from the fact that you had the adapter referencing the original list you created, and then you created a new list in createNewDeviceList(), and since the adapter was still pointing to the old list it could not see the changes.
The solution slartibartfast mentioned works because it clears the adapter and specifically adds the updated list to that adapter. Thus you don't have the problem of your adapter pointing to the wrong place.
Hope this helps someone!
your method addDevice is causing an endless loop. Dont call a method from itself like you are doing here :
deviceList = addDevice();

Categories