How do I stop SimpleDateFormat from updating the time - java

I saw that this was asked once at How to get current timestamp in Android without it updating like a clock, but it wasn't marked as answered and I don't understand the few suggestions that were given.
Anyway, I'm beyond new to Java and was following a tutorial on making a simple todo app (https://guides.codepath.com/android/Basic-Todo-App-Tutorial) and I decided to try to add a timestamp to each list item. I got as far as that it adds the current time, but its not static. The time keeps updating anytime I try and add a new item or if I close and reopen the app. I can't figure out/find the answer anywhere.
This is what I'm getting:
This is what I want:
Here's the code.
MainActivity.java
public class MainActivity extends AppCompatActivity {
private ArrayList<String> items;
private ArrayAdapter<String> TodoAdapter;
private ListView lvItems;
private void readItems() {
File filesDir = getFilesDir();
File todoFile = new File(filesDir, "todo.txt");
try {
items = new ArrayList<String>(FileUtils.readLines(todoFile));
} catch (IOException e) {
items = new ArrayList<String>();
}
}
private void writeItems() {
File filesDir = getFilesDir();
File todoFile = new File(filesDir, "todo.txt");
try {
FileUtils.writeLines(todoFile, items);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
items = new ArrayList<String>();
readItems();
TodoAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_2, android.R.id.text1, items);
lvItems = (ListView) findViewById(R.id.lvItems);
lvItems.setAdapter(TodoAdapter);
// Setup remove listener method call
setupListViewListener();
}
// Attaches a long click listener to the listview
// Removes item on long press
private void setupListViewListener() {
lvItems.setOnItemLongClickListener(
new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapter, View item, int pos, long id) {
// Remove the item within array at position
items.remove(pos);
// Refresh the adapter
TodoAdapter.notifyDataSetChanged();
writeItems();
// Return true consumes the long click event (marks it handled)
return true;
}
});
}
public void onAddItem(View v) {
EditText etNewItem = (EditText) findViewById(R.id.etNewItem);
String itemText = etNewItem.getText().toString();
TodoAdapter.add(itemText); // Add items to new Adapter type
etNewItem.setText("");
writeItems();
}
}
TodoAdapter.java
public class TodoAdapter extends ArrayAdapter<Todo> {
public TodoAdapter(Context context, ArrayList<Todo> items) {
super(context, 0, items);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Todo item = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(android.R.layout.simple_list_item_2, parent, false);
}
TextView text1 = (TextView) convertView.findViewById(android.R.id.text1);
TextView text2 = (TextView) convertView.findViewById(android.R.id.text2);
text1.setText(item.itemText);
text2.setText(item.getCreationTimeString());
text2.setTextSize(10);
return convertView;
}
}
Todo.java
public class Todo {
String itemText;
private Date creationTime;
public Todo(String text) {
this.itemText = text;
this.creationTime = new Date();
}
public String getCreationTimeString() {
return new SimpleDateFormat("h:mm a").format(creationTime);
}
}
Any help provided would be extremely appreciated. Also please keep in mind that I have literally almost no understanding of what I'm doing. :)

The time keeps updating anytime I try and add a new item
Right, that is because the Adapter is recalling new Date(), which will always get the current time that the View is created for an Adapter item.
It would appear that you want items to be associated with a time at which they are created. If that is the case, then you can make a class
public class Todo {
String itemText;
private Date creationTime;
public Todo(String text) {
this.itemText = text;
this.creationTime = new Date();
}
public String getCreationTimeString() {
return new SimpleDateFormat("h:mm a").format(creationTime);
}
}
Then, you should probably make an ArrayAdapter<Todo> to display these items and display something like this
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Todo item = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(android.R.layout.simple_list_item_2, parent, false);
}
TextView text1 = (TextView) convertView.findViewById(android.R.id.text1);
TextView text2 = (TextView) convertView.findViewById(android.R.id.text2);
text1.setText(item.itemText);
text2.setText(item.getCreationTimeString());
text2.setTextSize(10);
return convertView;
}
And update the add method
public void onAddItem(View v) {
EditText etNewItem = (EditText) findViewById(R.id.etNewItem);
String itemText = etNewItem.getText().toString();
itemsAdapter.add(new Todo(itemText)); // Add items to new Adapter type
etNewItem.setText("");
writeItems();
}

Related

Android Spinner value does not change in new Activity

I use a spinner in my App to open the same Activity but with different values to download Json files and show them. The first problem was, that the spinner don´t work, when i don´t add a spinner value at the 0 position and query it with if-statement (if(position >0)) in the onItemSelected method before open a new activity. Its a solution but not a very good.
The next problem is, that the value of the spinner shows every time the 0 position of the spinner list. Its same when i make a Array to fill the spinner or different Strings. Open the same Activity with different json files works fine but the spinner is all the time on position 0 value.
public class FragmentResult extends Fragment implements
GestureOverlayView.OnGesturePerformedListener, AdapterView.OnItemSelectedListener {
private ArrayList<ResultModel> arrayListResult = new ArrayList<>();
public static int dayOfMatch = 34;
private GestureLibrary gestureLibrary;
Spinner spinnerDay;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//matchDayCheck();
ServerResult serverResult = new ServerResult(getActivity().getApplicationContext(),
"https://www.dein-weg-in-die-cloud.de/tomcat7/RestSoccer/fussball/spieltag/" + dayOfMatch);
serverResult.execute();
String downResult = null;
try {
downResult = serverResult.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
JsonParser jsonParser = new JsonParser();
arrayListResult = jsonParser.parseJSONResult(downResult);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
GestureOverlayView gestureOverlayView = new GestureOverlayView(getActivity());
View view = inflater.inflate(R.layout.layout_result, container, false);
ListView result_list = (ListView)view.findViewById(R.id.result_list);
AdapterResult adapterResult = new AdapterResult(getActivity().getApplicationContext(), arrayListResult);
result_list.setAdapter(adapterResult);
gestureOverlayView.addView(view);
gestureOverlayView.setFadeEnabled(false);
gestureOverlayView.addOnGesturePerformedListener(this);
gestureOverlayView.setGestureColor(Color.TRANSPARENT);
gestureOverlayView.setUncertainGestureColor(Color.TRANSPARENT);
gestureOverlayView.setFadeOffset(0);
gestureOverlayView.setHapticFeedbackEnabled(true);
gestureLibrary = GestureLibraries.fromRawResource(getActivity().getApplicationContext(), R.raw.gestures); //!!
if (!gestureLibrary.load()) {
getActivity().finish();
}
// Spinner element
Spinner spinnerYear = (Spinner)view.findViewById(R.id.spinnerResultYear);
spinnerDay = (Spinner)view.findViewById(R.id.spinnerResultDay);
// Spinner click listener
spinnerYear.setOnItemSelectedListener(this);
spinnerDay.setOnItemSelectedListener(this);
// Spinner Drop down elements
List<String> spinnerListYear = new ArrayList<String>();
spinnerListYear.add("2013/2014");
List<String> spinnerListDay = new ArrayList<String>();
spinnerListDay.add("");
for(int i = 1; i<=34; i++){
spinnerListDay.add(i + ".Spieltag");
}
// Creating adapter for spinner
ArrayAdapter<String> spinnerYearAdapter = new ArrayAdapter<String>(getActivity().getApplicationContext(), android.R.layout.simple_spinner_item, spinnerListYear);
ArrayAdapter<String> spinnerDayAdapter = new ArrayAdapter<String>(getActivity().getApplicationContext(), android.R.layout.simple_spinner_item, spinnerListDay);
// Drop down layout style - list view with radio button
spinnerYearAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerDayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// attaching data adapter to spinner
spinnerYear.setAdapter(spinnerYearAdapter);
spinnerDay.setAdapter(spinnerDayAdapter);
/*result_list.setOnItemClickListener(new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ResultModel resultModel = (ResultModel) parent.getItemAtPosition(position);
int matchId = resultModel.getMatchId();
Intent matchIntent = new Intent(getActivity(), MatchActivity.class);
matchIntent.putExtra("MatchId", matchId);
matchIntent.putExtra("Matchday", dayOfMatch);
startActivity(matchIntent);
}
});*/
return gestureOverlayView;
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// On selecting a spinner item
String item = parent.getItemAtPosition(position).toString();
if(position >0) {
final Intent intent;
intent = new Intent(getActivity().getApplicationContext(), ResultActivity.class);
dayOfMatch = position;
intent.putExtra("dayOfMatch", dayOfMatch);
startActivity(intent);
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
.
.
.
}

Updating listView without duplication

I am writing a music player application with playlists, and I am trying to display the songs that have been chosen. All of the code for that works fine, but when a song is added, the listView won't update. I have searched extensively online, but cannot figure out how to fix it. I ended up trying to call leftAdapter.notifyDataSetChanged(); to update the list, but it throws the error:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ArrayAdapter.notifyDataSetChanged()' on a null object reference
I have also tried calling the initializing method (createLeftList()) but it duplicates all of the items in the list.
Method called to initialize listview:
public void createLeftList() {
DatabaseHandler db = new DatabaseHandler(this);
leftSongView = (ListView) findViewById(R.id.left_playlistView);
db.getAllsongs();
ArrayAdapter<String> leftAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, ArrayofName);
leftSongView.setAdapter(leftAdapter);
leftSongView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
Toast.makeText(getApplicationContext(), ((TextView) v).getText(), Toast.LENGTH_SHORT).show();
}
});
}
Method to fetch list and send to listview
public List<LeftPlaylist> getAllsongs() {
List<LeftPlaylist> leftPlaylistList = new ArrayList<LeftPlaylist>();
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_PLAYLIST;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
LeftPlaylist leftPlaylist = new LeftPlaylist();
leftPlaylist.setID(Integer.parseInt(cursor.getString(0)));
leftPlaylist.setName(cursor.getString(1));
leftPlaylist.setPath(cursor.getString(2));
String name = cursor.getString(1) +"\n"+ cursor.getString(2);
ListenPage.ArrayofName.add(name);
// Adding song to list
leftPlaylistList.add(leftPlaylist);
} while (cursor.moveToNext());
}
Method called to update the listview after modifying it:
public void updateLeftList(){
leftAdapter.notifyDataSetChanged();
}
Any help would be greatly appreciated!
Here is my SongAdapter code:
public class SongAdapter extends BaseAdapter {
private ArrayList<Song> songs;
private LayoutInflater songInf;
public SongAdapter(Context c, ArrayList<Song>theSongs){
songs=theSongs;
songInf=LayoutInflater.from(c);
}
#Override
public int getCount() {
return songs.size();
}
#Override
public Object getItem(int arg0) {
return null;
}
#Override
public long getItemId(int arg0) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//map to song layout
LinearLayout songLay = (LinearLayout)songInf.inflate
(R.layout.song, parent, false);
//get title and artist views
TextView songView = (TextView)songLay.findViewById(R.id.song_title);
TextView artistView = (TextView)songLay.findViewById(R.id.song_artist);
//get song using position
Song currSong = songs.get(position);
//get title and artist strings
songView.setText(currSong.getTitle());
artistView.setText(currSong.getArtist());
//set position as tag
songLay.setTag(position);
return songLay;
}
}
Do this in your Activity Class.
public class MyActivity extends Activity {
private SongListAdapter _songListAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
createLeftList();
}
private void createLeftList(){
DatabaseHandler db = new DatabaseHandler(this);
ListView leftSongView = (ListView) findViewById(R.id.left_playlistView);
_songListAdapter = new SongListAdapter(this, db.getAllsongs());
leftSongView.setAdapter(_songListAdapter);
}
//TODO use this whenever you wanna update your list.
public void updateSongView(List<String> songsList){
if(_songListAdapter != null && songsList != null){
_songListAdapter.updateMusicList(songsList);
}
}
}
Then create and Adapter class and follow the pattern.
public class SongListAdapter extends BaseAdapter{
private Context _context;
private List<String> musicList = new ArrayList();
public SongListAdapter(Context context, List<String> musicList){
_context = context;
this.musicList.clear();
this.musicList.addAll(musicList);
}
public void updateMusicList(List<String> musicList){
this.musicList.clear();
this.musicList.addAll(musicList);
notifyDataSetChanged();
}
#Override
public int getCount() {
return musicList.size();
}
#Override
public Object getItem(int position) {
return musicList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = LayoutInflater.from(_context).inflate(R.layout.music_view, parent, false);
// TODO folow view holder pattern.
}
String music = (String) getItem(position);
if(music != null){
//TODO update your views Here
}
return convertView;
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
//TODO peform any custon action when this is called if needed.
}
}

How to show chats by collecting messages in the custom list view adapter itself?

So, What I want to do is display chats in my activity using a custom list view adapter.
I have a HTTPTask Activity handling the server side interaction and responding with a JSONObject. So, every server side interaction is working fine.
What I want to do is keep updating the messages in the chat by keep checking with the API at a set interval to populate messages in the chat if there are any.
My question is, should this population process done in the adapter or the activity and how?
And, how does viewHolder help in the adapter?
This is my Activity
public class ChatActivity extends Activity {
TextView toUsername;
EditText replyText;
JSONObject resultObject;
StringBuilder reply,from_user_id,c_id;
MessageListViewAdapter myAdapter;
ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
toUsername = (TextView) findViewById(R.id.toUsername);
replyText = (EditText) findViewById(R.id.replyText);
reply = new StringBuilder("");
listView = (ListView) findViewById(R.id.messages);
}
#Override
public void onResume(){
super.onResume();
Bundle bundle = getIntent().getExtras();
if(bundle != null){
toUsername.setText("" + bundle.get("ToUsername").toString());
c_id = new StringBuilder(bundle.get("c_id").toString());
from_user_id = new StringBuilder(bundle.get("FromUserId").toString());
}
myAdapter = new MessageListViewAdapter(getBaseContext(),c_id.toString(),from_user_id.toString());
listView.setAdapter(myAdapter);
}
public void sendTextMsg(View view){
reply.delete(0,reply.length());
reply.append(replyText.getText().toString());
if(!reply.toString().equals("")){
Log.d("Values: ","c_id: " + c_id.toString() + " FromUserId: " + from_user_id.toString() + "ReplyText: " + reply.toString());
try{
resultObject = new HttpTask(getBaseContext()).doInBackground("replyInChat",c_id.toString(),replyText.getText().toString(),from_user_id.toString());
if(resultObject.get("status").toString().equals("true")) {
Toast.makeText(getBaseContext(), "Sent.", Toast.LENGTH_SHORT).show();
replyText.setText("");
}
else {
Toast.makeText(getBaseContext(), "Try Again.", Toast.LENGTH_SHORT).show();
}
}
catch(JSONException e){ }
}
}
}
My Adapter doesn't seem to work.
public class MessageListViewAdapter extends BaseAdapter implements ListAdapter{
private ArrayList<String> list = new ArrayList<String>();
private Context context;
private StringBuilder conversation_id, user_id;
private static int cr_id;
private JSONArray messages;
private JSONObject resultObject;
private ViewHolder viewHolder;
private View rowView;
public MessageListViewAdapter(Context context, String conversation_id, String user_id) {
this.context = context;
this.conversation_id = new StringBuilder(conversation_id.toString());
this.user_id = new StringBuilder(user_id.toString());
cr_id=0;
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int pos) {
return list.get(pos);
}
#Override
public long getItemId(int pos) {
//return list.get(pos).getId();
//just return 0 if your list items do not have an Id variable.
return 0;
}
#Override
public boolean isEnabled(int position){
return false;
}
static class ViewHolder{
public TextView ItemText;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
rowView = convertView;
if (rowView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.message_list_layout, null);
//configure view holder
viewHolder = new ViewHolder();
viewHolder.ItemText = (TextView) rowView.findViewById(R.id.list_item_text);
rowView.setTag(viewHolder);
}
else {
//fill data
viewHolder = (ViewHolder) rowView.getTag();
}
try{
Log.d("cr_id: ",String.valueOf(cr_id).toString());
//This is where the population should've taken place but didn't.
resultObject = new HttpTask(context).doInBackground("sendMessages",conversation_id.toString(),String.valueOf(cr_id));
if(resultObject.get("status").toString().equals("true")) {
messages = resultObject.getJSONArray("messages");
Log.d("Messages: ",messages.toString());
for(int i=0;i<=messages.length();i++){
list.add(messages.getJSONObject(i).get("reply_text").toString());
}
}
}
catch(JSONException e){ }
//Handle TextView and display string from your list
//final TextView listItemText = (TextView)rowView.findViewById(R.id.list_item_text);
//listItemText.setText(list.get(position));
viewHolder.ItemText.setText(list.get(position));
return rowView;
}
}
If every thing is working fine and you have problem in showing latest chat message in adapter just change your code like this:
try{
Log.d("cr_id: ",String.valueOf(cr_id).toString());
//This is where the population should've taken place but didn't.
resultObject = new HttpTask(context).doInBackground("sendMessages",conversation_id.toString(),String.valueOf(cr_id));
if(resultObject.get("status").toString().equals("true")) {
messages = resultObject.getJSONArray("messages");
Log.d("Messages: ",messages.toString());
for(int i=0;i<=messages.length();i++){
list.add(messages.getJSONObject(i).get("reply_text").toString());
this.notifyDataSetChanged(); // add this line
}
}
}
catch(JSONException e){ }
Comment below for any further information
Personally i would do the network calls outside of the adapter. With the code currently if the user was to scroll up and down the list the network call would call multiple times which is something im sure you dont want.
What may be a better solution is having a method inside the activity that does the call, then have a timer set up that calls that method say every 2 - 3 minutes to save on the network calls, you could also add a refresh button for the user which gives them the choice of refreshing the data themselves which would just call the same method.
The View Holder design pattern can help speed up a listview and keep it smooth, Think of it this way, when the page first loads, getView will be called a number of times to fill up the list view. In the getView method you instantiate your UI widgets i.e textview = (TextView)findviewbyid. Now what the view holder does is keep a reference to these ui elements which means you wont have to keep calling findViewById.
Here is an article that explains it a bit better and go into some examples.
http://www.javacodegeeks.com/2013/09/android-viewholder-pattern-example.html
So lets say you do the network code in the activity. When you get a response you can simply add the message to the list then notifyDataSetChanged();
So, Finally I got it working with some experimentation. Many thanks to Manikanta and Andy Joyce for their valuable answers. If it weren't for them i wouldn't have gone any further from where I was stuck.
This is what I changed in my custom adapter.
public void add(ArrayList<String> list){
this.list.clear();
this.list.addAll(list);
Log.d("List: ",this.list.toString());
this.notifyDataSetChanged();
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
rowView = convertView;
if (rowView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.message_list_layout, null);
//configure view holder
viewHolder = new ViewHolder();
viewHolder.ItemText = (TextView) rowView.findViewById(R.id.list_item_text);
rowView.setTag(viewHolder);
}
else {
//fill data
viewHolder = (ViewHolder) rowView.getTag();
}
viewHolder.ItemText.setText(list.get(position));
return rowView;
}
This is what I added to my activity
#Override
public void onResume(){
super.onResume();
Bundle bundle = getIntent().getExtras();
if(bundle != null){
toUsername.setText("" + bundle.get("ToUsername").toString());
c_id = new StringBuilder(bundle.get("c_id").toString());
from_user_id = new StringBuilder(bundle.get("FromUserId").toString());
//list.add(c_id.toString());
//list.add(from_user_id.toString());
}
myAdapter = new MessageListViewAdapter(getBaseContext(),c_id.toString(),from_user_id.toString());
listView.setAdapter(myAdapter);
callAsynchronousTask();
//myAdapter.add(list);
}
#Override
public void onPause(){
super.onPause();
timer.cancel();
}
public void callAsynchronousTask() {
final Handler handler = new Handler();
timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
//list.clear();
try{
resultChatObject = new HttpTask(getBaseContext()).doInBackground("sendMessages",c_id.toString(),String.valueOf(cr_id));
if(resultChatObject.get("status").toString().equals("true")) {
//list.clear();
messages = resultChatObject.getJSONArray("messages");
Log.d("Messages: ",messages.toString());
for (int i = 0; i <= messages.length(); i++) {
list.add(messages.getJSONObject(i).get("reply_text").toString());
if (cr_id < Integer.parseInt(messages.getJSONObject(i).get("cr_id").toString()))
cr_id = Integer.parseInt(messages.getJSONObject(i).get("cr_id").toString());
}
}
}
catch (JSONException e) { }
myAdapter.add(list);
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 10000); //execute in every 10000 ms
}
Cheers everyone!!!

How to access elements in a ListView when long clicked

I am working on an application that has a ListView of movies. The list is declared as an array in strings.xml. It has elements, Title, Gross and Date Released. When a row is long clicked, it brings up a context menu that allows the user to edit said row or delete it. When the user picks Edit, he/she is brought to a 2nd screen with 3 Edit Text corresponding to Title, Gross and Date. The EditText fields are initialized with the data from the clicked row. Here is my code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] titleList = getResources().getStringArray(R.array.title_array);
String[] grossList = getResources().getStringArray(R.array.gross_array);
String[] dateList = getResources().getStringArray(R.array.date_array);
results = new ArrayList<Lab8_082588FetchDetails>();
for (int i = 0; i < titleList.length; i++) {
Lab8_082588FetchDetails sr = new Lab8_082588FetchDetails();
sr.setTitle(titleList[i]);
sr.setGross(grossList[i]);
sr.setDate(dateList[i]);
results.add(sr);
}
adapter = new SampleCustomAdapter(results);
setListAdapter(adapter);
ListView lv = getListView();
lv.setTextFilterEnabled(true);
registerForContextMenu(lv);
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
// TODO Auto-generated method stub
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
// places the contents of the XML to the menu
inflater.inflate(R.menu.context_menu, menu);
}
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
.getMenuInfo();
switch (item.getItemId()) {
case R.id.delete:
results.remove(info.position);
adapter.notifyDataSetChanged();
return true;
case R.id.edit:
System.out.println(info.id);
System.out.println(info.position);
Intent newData = new Intent(Lab8_082588.this, Lab8_082588Edit.class);
results.get(info.position);
TextView movieTitle = (TextView) findViewById(R.id.title);
TextView movieGross = (TextView) findViewById(R.id.gross);
TextView movieDate = (TextView) findViewById(R.id.date);
String startTitle = movieTitle.getText().toString();
String startGross = movieGross.getText().toString();
String startDate = movieDate.getText().toString();
newData.putExtra(Lab8_082588Edit.TITLE_STRING, startTitle);
newData.putExtra(Lab8_082588Edit.GROSS_STRING, startGross);
newData.putExtra(Lab8_082588Edit.DATE_STRING, startDate);
startActivityForResult(newData, Lab8_082588.EDIT_MOVIE);
return true;
default:
return super.onContextItemSelected(item);
}
}
For the Edit screen:
public class Lab8_082588Edit extends Activity {
public static final String TITLE_STRING = "TITLE_STRING";
public static final String GROSS_STRING = "GROSS_STRING";
public static final String DATE_STRING = "DATE_STRING";
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.addedit);
initialize();
}
private void initialize() {
// TODO Auto-generated method stub
Intent prepopulate = getIntent();
EditText movieTitle = (EditText) findViewById(R.id.etTitle);
EditText movieGross = (EditText) findViewById(R.id.etGross);
EditText movieDate = (EditText) findViewById(R.id.etDate);
String startTitle = prepopulate.getStringExtra(Lab8_082588Edit.TITLE_STRING);
String startGross = prepopulate.getStringExtra(Lab8_082588Edit.GROSS_STRING);
String startDate = prepopulate.getStringExtra(Lab8_082588Edit.DATE_STRING);
movieTitle.setText(startTitle);
movieGross.setText(startGross.replaceAll(",", "").replace("$", ""));
movieDate.setText(startDate);
}
My FetchDetails class
public class Lab8_082588FetchDetails implements Comparable<Lab8_082588FetchDetails> {
private String title;
private String gross;
private String date;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getGross() {
return gross;
}
public void setGross(String gross) {
this.gross = gross;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
#Override
public int compareTo(Lab8_082588FetchDetails another) {
// TODO Auto-generated method stub
return title.compareTo(another.title);
}
}
My Adapter:
private class SampleCustomAdapter extends BaseAdapter {
public SampleCustomAdapter(ArrayList<Lab8_082588FetchDetails> movies) {
internalList = movies;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return internalList.size();
}
#Override
public Object getItem(int index) {
// TODO Auto-generated method stub
return internalList.get(index);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View view;
if (convertView == null) {
view = inflater.inflate(R.layout.row, null);
} else {
view = convertView;
}
// extract the views to be populated
TextView title = (TextView) view.findViewById(R.id.title);
TextView gross = (TextView) view.findViewById(R.id.gross);
TextView date = (TextView) view.findViewById(R.id.date);
// extract the object that will fill these
Lab8_082588FetchDetails movie = internalList.get(position);
title.setText(movie.getTitle());
date.setText(movie.getDate());
gross.setText(movie.getGross());
// return the view
return view;
}
}
My problem is that, indeed, the Edit Texts get populated, but only with the data from the first item in the entire list (e.g. Titanic is first on the list, and is the only one being populated). Even if I click the nth row movie in the listview, Titanic is still the one being retrieved. How do I solve this?
Edit: I realize that somehow, the code is only considering the first element of the list. How do I access the elements of the other rows?
I realize that somehow, the code is only considering the first
element of the list. How do I access the elements of the other rows?
You should never do a search with findViewById for items which are in a ListView row. In the onContextItemSelected callback you have the position of the element clicked so you could use it to get the data associated with this row:
case R.id.edit:
Intent newData = new Intent(Lab8_082588.this, Lab8_082588Edit.class);
// I hope you implemented the adapter correctly
Lab8_082588FetchDetails item = (Lab8_082588FetchDetails) getListView().getItemAtPosition(info.position);
String startTitle = item.getTitle();
String startGross = item.getGross();
String startDate = item.getDate();
newData.putExtra(Lab8_082588Edit.TITLE_STRING, startTitle);
newData.putExtra(Lab8_082588Edit.GROSS_STRING, startGross);
newData.putExtra(Lab8_082588Edit.DATE_STRING, startDate);
startActivityForResult(newData, Lab8_082588.EDIT_MOVIE);
return true;

Custom ListView is not updated when items are inserted

I have a custom listview with custom adapter extending BaseAdapter if i add items to this list view in OnCreate method they show up in list, but if i add them from other methods like a packet listener method then items do not show up , on the screen below this listview there is a textbox if i select textbox to entertext using virtual keyboard immediately the listview gets populated with previousely inserted items which didnt show up. This activity is a chat window basically
I have tried calling notifyDataSetChanged, invalidate on Layout or on listview but nothing helped.
What i think is i need to have a way to refresh activity , as same thing must be happening when the virtual keyboard pops up .
Help will be highly appreciated
Thanks
Code:
package com.arounds;
public class ChatActivity extends Activity implements OnClickListener,PacketListener{
private ListView chatView;
private ChatListViewCustomAdapter adapter;
private String user;
private XMPPConnection connection;
private Conversation conv;
private ChatActivity selfRef = this;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chat_win);
AroundApplication app = (AroundApplication) this.getApplicationContext();
connection = app.getConnection();
chatView = (ListView) findViewById(R.id.conversationList);
adapter = new ChatListViewCustomAdapter(this);
chatView.setAdapter(adapter);
// set send btn listener
ImageButton send = (ImageButton)findViewById(R.id.imgBtnSend);
send.setOnClickListener(this);
ImageButton smiley = (ImageButton)findViewById(R.id.imgBtnSmiley);
smiley.setOnClickListener(this);
// get the parameter passed by previouse activity
Bundle b = this.getIntent().getExtras();
String temp = b.getString("user");
user = temp;
TextView v = (TextView)this.findViewById(R.id.txtViewTitle_chat);
v.setText(temp);
v = (TextView)this.findViewById(R.id.txtViewDescription_chat);
temp = b.getString("status");
v.setText(temp);
//chatView.setOnItemClickListener(this);
HashMap convs = app.getConversations();
if(convs.containsKey(user) == true)
conv = (Conversation) convs.get(user);
else {
conv = new Conversation();
convs.put(user,conv);
}
PacketFilter filter = new MessageTypeFilter(Message.Type.chat);
connection.addPacketListener(this,filter);
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v.getId() == R.id.imgBtnSend)
{
EditText msg = (EditText)this.findViewById(R.id.editChat);
String s = msg.getText().toString();
Message message = new Message(user, Message.Type.chat);
message.setBody(s);
connection.sendPacket(message);
ArrayList<ChatMessage> m = conv.messages;
String currentDate = DateFormat.getDateInstance().format(new Date());
m.add(new ChatMessage(s,currentDate));
adapter.addItem("I said",s,currentDate,Constants.SEND_LIST_TYPE);
//adapter.notifyDataSetChanged();
}
else
{
//View view = this.findViewById(R.id.linerLayoutChat);
chatView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}
#Override
public void processPacket(Packet packet) {
// TODO Auto-generated method stub
System.out.println("in");
Message message = (Message) packet;
if (message.getBody() != null) {
System.out.println("in1");
String fromName = StringUtils.parseBareAddress(message.getFrom());
ArrayList<ChatMessage> m = conv.messages;
String currentDate = DateFormat.getDateInstance().format(new Date());
m.add(new ChatMessage(message.getBody(),currentDate));
adapter.addItem(fromName+" said",message.getBody(),currentDate,Constants.REC_LIST_TYPE);
//chatView.postInvalidate();
}
}
}
Adapter class:
public class ChatListViewCustomAdapter extends BaseAdapter
{
public ArrayList<ChatListItem> items;
public Activity context;
public LayoutInflater inflater;
public Boolean temp=false;
public ChatListViewCustomAdapter(Activity context) {
super();
this.context = context;
this.items = new ArrayList<ChatListItem>();
this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return items.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
public static class ViewHolder
{
TextView txtViewTitle;
TextView txtViewDescription;
TextView txtViewDate;
}
public void addItem(String title,String desc,String d,int type)
{
ChatListItem item = new ChatListItem(title,desc,d,type);
items.add(item);
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ChatListItem item = items.get(position);
ViewHolder holder;
System.out.println("Title:"+item.title+" type:"+item.type);
if(convertView==null)
{
holder = new ViewHolder();
int type = this.getItemViewType(position);
if(type == 0)
{
convertView = inflater.inflate(R.layout.list_item_even, null);
holder.txtViewTitle = (TextView) convertView.findViewById(R.id.txtViewTitleEven);
holder.txtViewDescription = (TextView) convertView.findViewById(R.id.txtViewDescriptionEven);
holder.txtViewDate = (TextView) convertView.findViewById(R.id.txtViewDateEven);
}
else
{
convertView = inflater.inflate(R.layout.list_item_odd, null);
holder.txtViewTitle = (TextView) convertView.findViewById(R.id.txtViewTitleOdd);
holder.txtViewDescription = (TextView) convertView.findViewById(R.id.txtViewDescriptionOdd);
holder.txtViewDate = (TextView) convertView.findViewById(R.id.txtViewDateOdd);
}
convertView.setTag(holder);
}
else
holder=(ViewHolder)convertView.getTag();
holder.txtViewTitle.setText(item.title);
holder.txtViewDescription.setText(item.desc);
holder.txtViewDate.setText(item.date);
return convertView;
}
#Override
public int getItemViewType(int position) {
ChatListItem item = items.get(position);
return item.type;
}
#Override
public int getViewTypeCount() {
return 2;
}
}
Handle all the updates within your Adapter and ensure you invoke notifyDataSetChanged() after you update it (within your Adapter)?
In cases where notifyDataSetChanged() does not work, re-set the adapter on the ListView by calling ListView.setAdapter() with the same Adapter again. This should refresh the view.
the only thing I can see not right are these methods:
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
These methods should return proper values.
items.get(position) and position respectively.

Categories

Resources