Out-of-sync ArrayAdapter with Autocomplete - android

I have 3 classes, I wish to use the autocomplete text box to show user certain data (aka cities) from a web service (rest api). I've used this implementation on various features of my own application, but for some reason, there's a synchronization problem within the textchangedlistener...
CitiesArrayAdapter.java (to show a different view, in my case the "city, state"):
package com.android.lzgo.adapters;
import java.util.ArrayList;
import java.util.List;
import com.android.lzgo.activities.LiftSearchActivity;
import com.android.lzgo.activities.R;
import com.android.lzgo.models.City;
import com.android.lzgo.models.Lift;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class CitiesArrayAdapter extends ArrayAdapter<City> {
private static final String TAG = CitiesArrayAdapter.class.getName();
private final ArrayList<City> cities;
private int viewResourceId;
public CitiesArrayAdapter(Context context, int textViewResourceId, ArrayList<City> results) {
super(context, textViewResourceId, results);
this.cities = results;
this.viewResourceId = textViewResourceId;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// assign the view we are converting to a local variable
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(viewResourceId, null);
}
City i = cities.get(position);
Log.d(TAG, "Here is my value: " + i);
if (i != null) {
TextView tt = (TextView) v.findViewById(android.R.id.text1);
Log.d(TAG, "Name: " + i.getName() + ", " + i.getProvince_name());
if (tt != null){
tt.setText("Name: " + i.getName() + ", " + i.getProvince_name());
}
}
// the view must be returned to our activity
return v;
}
}
CitiesResponderFragment.java (this is how I get my values from my rest api):
package com.android.lzgo.fragment;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import com.android.lzgo.activities.LiftSearchActivity;
import com.android.lzgo.definitions.Constants;
import com.android.lzgo.models.City;
import com.android.lzgo.service.LzgoService;
import com.google.gson.Gson;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.Toast;
public class CitiesResponderFragment extends LzgoResponderFragment {
private static String TAG = CitiesResponderFragment.class.getName();
private List<City> mCities;
ArrayAdapter<City> adapter;
private String enteredCharacters;
LiftSearchActivity activity;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
activity = (LiftSearchActivity) getActivity();
// This gets called each time our Activity has finished creating itself.
getCities();
}
private void getCities() {
if (mCities == null && activity != null) {
Intent intent = new Intent(activity, LzgoService.class);
intent.setData(Uri.parse(Constants.REST_CITIES_AUTOCOMPLETE));
Bundle params = new Bundle();
params.putString("search", getenteredCharacters());
intent.putExtra(LzgoService.EXTRA_HTTP_VERB, LzgoService.GET);
intent.putExtra(LzgoService.EXTRA_PARAMS, params);
intent.putExtra(LzgoService.EXTRA_RESULT_RECEIVER, getResultReceiver());
// Here we send our Intent to our RESTService.
activity.startService(intent);
}
}
#Override
public void onRESTResult(int code, String result) {
Log.e(TAG, Integer.toString(code));
Log.e(TAG, result);
// Check to see if we got an HTTP 200 code and have some data.
if (code == 200 && result != null) {
mCities = getCitiessFromJson(result);
adapter = activity.getArrayAdapter();
adapter.clear();
for( City city : mCities){
//debugging
Log.d(TAG, "City : " + city.getName());
adapter.add(city);
adapter.notifyDataSetChanged();
}
getCities();
}
else {
Activity activity = getActivity();
if (activity != null && code == 400) {
Toast.makeText(activity, result, Toast.LENGTH_SHORT).show();
}
else
Toast.makeText(activity, "Failed to load lzgo data. Check your internet settings.", Toast.LENGTH_SHORT).show();
}
}
private List<City> getCitiessFromJson(String json) {
ArrayList<City> cityList = new ArrayList<City>();
Gson gson = new Gson();
try {
JSONObject citiesWrapper = (JSONObject) new JSONTokener(json).nextValue();
JSONArray cities = citiesWrapper.getJSONArray("cities");
for (int i = 0; i < cities.length(); i++) {
//JSONObject city = cities.getJSONObject(i);
String jsonCity = cities.getString(i);
City city = gson.fromJson( jsonCity, City.class );
//Log.e(TAG, "Hurray! Parsed json:" + city.getString("name"));
//cityList.add(city.getString("name"));
cityList.add(city);
}
}
catch (JSONException e) {
Log.e(TAG, "Failed to parse JSON.", e);
}
return cityList;
}
public String getenteredCharacters() {
return enteredCharacters;
}
public void setenteredCharacters(String characters) {
this.enteredCharacters = characters;
}
}
LiftSearchActivity.java (My FragmentActivity):
package com.android.lzgo.activities;
import java.util.ArrayList;
import com.android.lzgo.adapters.CitiesArrayAdapter;
import com.android.lzgo.fragment.CitiesResponderFragment;
import com.android.lzgo.models.City;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.AutoCompleteTextView;
import android.widget.DatePicker;
public class LiftSearchActivity extends FragmentActivity{
private static final String TAG = LiftSearchActivity.class.getName();
// User lift input
private AutoCompleteTextView autoCityFrom;
private AutoCompleteTextView autoCityTo;
private DatePicker date;
private CitiesArrayAdapter adapter;
private ArrayList<City> mCities ;
int year , month , day;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lift_search);
mCities = new ArrayList<City>();
adapter = new CitiesArrayAdapter(this,
android.R.layout.simple_dropdown_item_1line, mCities);
autoCityFrom = (AutoCompleteTextView) findViewById(R.id.cityFrom);
autoCityTo = (AutoCompleteTextView) findViewById(R.id.cityTo);
adapter.setNotifyOnChange(true);
autoCityFrom.setAdapter(adapter);
autoCityTo.setAdapter(adapter);
autoCityFrom.addTextChangedListener(new TextWatcher() {
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
// no need to do anything
}
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (((AutoCompleteTextView) autoCityFrom).isPerformingCompletion()) {
return;
}
if (charSequence.length() < 2) {
return;
}
String query = charSequence.toString();
getCities(query);
}
public void afterTextChanged(Editable editable) {
}
});
autoCityTo.addTextChangedListener(new TextWatcher() {
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
// no need to do anything
}
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (((AutoCompleteTextView) autoCityTo).isPerformingCompletion()) {
return;
}
if (charSequence.length() < 2) {
return;
}
String query = charSequence.toString();
getCities(query);
}
public void afterTextChanged(Editable editable) {
}
});
date = (DatePicker) findViewById(R.id.dpResult);
}
public void searchLifts(View view) {
Intent intent = new Intent(this, LiftsResultActivity.class);
//While autocomplete doesn't work hardcore value...
intent.putExtra("from", Integer.toString(9357)); // Sherbrooke
intent.putExtra("to", Integer.toString(6193)); // Montreal
intent.putExtra("date", Integer.toString(date.getMonth()+1) + "-" + Integer.toString(date.getDayOfMonth()) + "-" + Integer.toString(date.getYear()));
startActivity(intent);
}
public void getCities(String query) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
CitiesResponderFragment responder = (CitiesResponderFragment) fm.findFragmentByTag("RESTResponder");
responder = new CitiesResponderFragment();
responder.setenteredCharacters(query);
ft.add(responder, "RESTResponder");
ft.commit();
}
public CitiesArrayAdapter getArrayAdapter() {
// TODO Auto-generated method stub
return adapter;
}
}
I get the correct result and all. But my service doesn't seem to populate my array adapter in my activity, when I try to show my first "city", my adapter contains nothing. I wonder if I have to put a notifydatasetchanged (I tried, but doesn't work). I'm kind of confuse... any pointers?
While debugging the application I noticed that the properties mObjects of
the ArrayAdapter is cleared even if the associated ArrayList has
elements, and then properties mOriginalValues is filled with the
Strings loaded the first time.

Without seeing the full code base(+ data), I don't know if someone can pin point the reason for your code's failure. But I think the problem comes more from the way you setup the whole auto complete related code than some obvious line error. Below I'll try to address some of this issues(from my point of view) :
First of all, in the TextWatcher from LiftSearchActivity you call the getCities() method which adds, each time the user modifies the auto complete text, a Fragment to the Activity. I really doubt you want this, you should probably look at having only one Fragment in the Activity on which to call a refresh(or update) method, passing it the new filter text. If the user rotates the phone those fragments will also be recreated because of the configuration change.
Second, in the CitiesResponderFragment class you call the fragment's getCities() method(if you don't have any data) in onActivityCreated which start an update service(?!). Now related to the first point, you could end up doing a lot of unnecessary queries, for example if the user enter 4 characters and then decides to delete one of the characters as it was incorrect you'll end up with 5 added fragments, from which 3 will make the service start/query for data.
And last, I'm not sure if you understand how the AutoCompleteTextView works under the hood. In order to provide the drop down with the suggestions the AutoCompleteTextView widget will filter its adapter(adapter.getFilter()) and show as suggestions the items that match the filter. I don't know if you set some threshold on the AutoCompleteTextView but initially the auto complete will be empty for the first 3 characters entered as you start with an empty list of items when you first setup the Activity. The first two characters will not show anything because you start with an empty list and you don't add any new fragments(charSequence.length() < 2). The third character will most likely also not show anything, because the overhead of creating the fragment, starting the service and fetching the data will almost for sure be greater then doing the work of the adapter filtering(which will still see the initially empty list). I don't know if you tested, but from this fourth character the adapter should have some elements in it and the filtering should show something. Clearing the adapter and adding new data in it willl only make that data available to the next character entered in the AutoCompleteTextView.
The proper way of doing the filtering would be to further extend your adapter and implement the getFilter() method to return your own Filter implementation which would query the data store for new filtered items. The filtering method runs on a background thread, with a little work I think you could implement your current logic with the Service and the REST callback.

See example of the REST API Autocomplete : https://subversion.assembla.com/svn/rockitsearch-android/
Although it is part of my service, it can also serve as an example of how you can integrate your own REST API in AutoCompleteTextView control. If you are interested in autocomplete 3rd party service, here you go : www.rockitsearch.com

Related

How can I convert ListView population from JSON to SharedPreferences?

I have a listview in a fragment that is populated with a list of events. I have a heart icon on these list items that allows the user to click and favorite the items. I am currently saving the event id in sharedprefs when the item is Favorited.
This is working properly, and saves the favorited item across user sessions. I now need to populate these favorited items in the favorites listview. The old developer tried a JSON implementation from an api, but it never worked. I now just want to populate this list from the sharedprefs. Heres my favorites fragment code...
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;
import com.appsflyer.AppsFlyerLib;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import lakeviewlabs.ticketliquidator.api.delete_favorites.DeleteFavoritesApi;
import lakeviewlabs.ticketliquidator.api.delete_favorites.DeleteFavoritesApiOut;
import lakeviewlabs.ticketliquidator.api.get_favorites.GetFavoritesApi;
import lakeviewlabs.ticketliquidator.api.get_favorites.GetFavoritesApiOut;
import static com.urbanairship.UAirship.getApplicationContext;
public class FavoritesFragment extends Fragment implements GetFavoritesApiOut, DeleteFavoritesApiOut {
View rootView;
ProgressDialog pDialog;
FavoritesAdapter adapter;
Boolean checkState = false;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Map<String, Object> eventValue = new HashMap<String, Object>();
AppsFlyerLib.getInstance().trackEvent(getActivity().getApplicationContext(), "View Favorites",eventValue);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
Map<String,?> keys = prefs.getAll();
for(Map.Entry<String,?> entry : keys.entrySet()){
Log.d("map values",entry.getKey() + ": " +
entry.getValue());
if (entry.getKey().matches("[0-9]+") && entry.getValue().equals(true)) {
Log.d("using values",entry.getKey() + ": " +
entry.getValue());
// performersList.add(entry.getKey().);
}
}
rootView = inflater.inflate(R.layout.fragment_favorites, container, false);
GetFavoritesApi api = new GetFavoritesApi(getContext(), this);
rootView.findViewById(R.id.delete_favorites).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
deleteFavorites();
}
});
showLoadingMessage();
api.get();
return rootView;
}
private void deleteFavorites() {
ArrayList<String> ids = new ArrayList<String>();
ListView listView = (ListView) rootView.findViewById(R.id.favorites);
DeleteFavoritesApi api = new DeleteFavoritesApi(getContext(), this);
for (int i = 0; i < listView.getCount(); i++){
View view = listView.getChildAt(i);
CheckBox check = (CheckBox)view.findViewById(R.id.favorite_select);
if(check.isChecked()){
ids.add(view.getTag().toString());
}
}
if(ids.isEmpty()){
onDeleteFavoritesSuccess();
return;
}
api.delete(android.text.TextUtils.join(",", ids));
}
private void showLoadingMessage(){
pDialog = new ProgressDialog(getContext());
pDialog.setMessage("Getting favorite performers...");
pDialog.show();
}
#Override
public void onGetFavoritesSuccess(JSONArray favorites) {
ListView listView = (ListView) rootView.findViewById(R.id.favorites);
ArrayList<JSONObject> performersList = new ArrayList<JSONObject>();
for(int i = 0; i < favorites.length(); i++) {
JSONObject performer = null;
try {
performer = favorites.getJSONObject(i);
performersList.add(performer);
} catch (JSONException e) {
e.printStackTrace();
}
}
adapter = new FavoritesAdapter(getContext(), performersList);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new ListView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(checkState) {
CheckBox check = (CheckBox)view.findViewById(R.id.favorite_select);
check.setChecked(!check.isChecked());
}else{
Intent intent = new Intent(getContext(), PerformerActivity.class);
intent.putExtra("performer_id", view.getTag().toString());
startActivity(intent);
}
}
});
pDialog.dismiss();
}
#Override
public void onGetFavoritesError(JSONObject errors) {
}
#Override
public void onGetFavoritesUnexpectedError() {
}
public void showCheckboxes() {
checkState = !checkState;
rootView.findViewById(R.id.delete_favorites).setVisibility(checkState ? View.VISIBLE : View.INVISIBLE);
ListView listView = (ListView) rootView.findViewById(R.id.favorites);
for (int i = 0; i < listView.getCount(); i++){
View view = listView.getChildAt(i);
CheckBox check = (CheckBox)view.findViewById(R.id.favorite_select);
check.setVisibility(checkState ? View.VISIBLE : View.GONE);
check.setChecked(false);
// view.animate()
// .translationX(150)
// .setDuration(300)
// .setListener(new AnimatorListenerAdapter() {
// #Override
// public void onAnimationEnd(Animator animation) {
//
// }
// });
}
//
}
#Override
public void onDeleteFavoritesSuccess() {
GetFavoritesApi api = new GetFavoritesApi(getContext(), this);
showLoadingMessage();
showCheckboxes();
api.get();
}
}
I've tried parsing all the sharedprefs and Im able to log the ones that are needed. I just cant get them to display in the favorites list.
You can store the object of the item as JSON string in the Shared Preferences and whenever new item is added to favorites append the JSON object for that item to the JSON string and in the Favorites list read and parse the json string from Shared Preferences. I'm assuming you get the results in JSON array from the API. I would suggest store the JSON string in the same format as received so that you can reuse the same POJOs for favorites list.
Hope this helps.
You should not store your preferences like that. Storing your event using their ids as a key creates a big mess in your Shared Preferences.
Instead:
Store a list of event id. As you can't store a list in the Shared Preferences, use Gson to convert your list into a Json string. Then store the string. Use Gson again to regenerate the list from the stored string.
The other (better) option, is to use a local database. It's gonna be easier, and cleaner. You will be able to store more information easily. Like that you can store the entire event (and not the id only) and request them back to populate your ListView of favourite events
Note: You could store the entire events in the Shared Preferences as suggested by #Varun_Ramani but it's not recommended as the purpose of the Shared Preferences is not to replace databases (as explained in the official documentation, see below).
If you have a relatively small collection of key-values that you'd like to save, you should use the SharedPreferences APIs.

Save list favorites data static

I have different listview all same but now i have i problem. I want to create a method for saving favorite. Sorry for this simple question but I'm new on android and java. I know this data is static but I don't know is it possible make shared preference for saving this data.
import android.content.Intent;
import android.graphics.Color;
import android.renderscript.Sampler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.MobileAds;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ammunition extends AppCompatActivity {
String[] listaammunition = new String[]{"Arrow Zigzag","Arrow, Alchemist’s Fire(1)"};
EditText inputSearch;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ammunition);
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(getApplicationContext(),
android.R.layout.simple_list_item_1, listaammunition) {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
TextView text = (TextView) view.findViewById(android.R.id.text1);
text.setTextColor(Color.BLACK);
return view;
}
};
ListView listViewammunition = (ListView) findViewById(R.id.listViewammunition);
listViewammunition.setAdapter(adapter);
inputSearch = (EditText) findViewById(R.id.inputSearchmunizioni);
inputSearch.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
adapter.getFilter().filter(s);
}
#Override
public void afterTextChanged(Editable s) {
}
});
listViewammunition.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String Arrowalchemistsfire = adapter.getItem(position);
if (Arrowalchemistsfire.equals("Arrow, Alchemist’s Fire(1)")) {
Intent Arrowalchemistsfire1 = new Intent(getApplicationContext(), dettagli_armi.class);
Arrowalchemistsfire1.putExtra("costo", "75 gp");
Arrowalchemistsfire1.putExtra("dannis", "1D4");
Arrowalchemistsfire1.putExtra("dannim", "1D4");
Arrowalchemistsfire1.putExtra("crit", "x2");
Arrowalchemistsfire1.putExtra("rangeinc", "30 ft.");
Arrowalchemistsfire1.putExtra("weight", "1/5 lb.");
Arrowalchemistsfire1.putExtra("type", "fire");
Arrowalchemistsfire1.putExtra("dettagli", "Each of these projectiles carries a deadly load of alchemist's fire in its hollow shaft.\n" +
" When it strikes a target, the arrow's shaft shatters, releasing the alchemist's fire directly onto the target. One round after impact, the alchemist's fire ignites, dealing 1d4 points of damage.\n" +
"\n" +
" The target can use a full-round action to attempt to extinguish the flames before taking this damage. It takes a successful Reflex saving throw (DC 15) to extinguish the flames.\n" +
" Rolling on the ground earns the target a +2 bonus on the save. Submerging (such as by leaping into a lake) or magically extinguishing the flames automatically kills the flames.\n");
Arrowalchemistsfire1.putExtra("Source", "Dragon #349");
startActivity(Arrowalchemistsfire1);
}
String Arrowalchemistsfrost = adapter.getItem(position);
if (Arrowalchemistsfrost.equals("Arrow, Alchemist’s Frost(1)")) {
Intent Arrowalchemistsfrost1 = new Intent(getApplicationContext(), dettagli_armi.class);
Arrowalchemistsfrost1.putExtra("costo", "75 gp");
Arrowalchemistsfrost1.putExtra("dannis", "1D4");
Arrowalchemistsfrost1.putExtra("dannim", "1D4");
Arrowalchemistsfrost1.putExtra("crit", "x2");
Arrowalchemistsfrost1.putExtra("rangeinc", "30 ft.");
Arrowalchemistsfrost1.putExtra("weight", "1/5 lb.");
Arrowalchemistsfrost1.putExtra("type", "cold");
Arrowalchemistsfrost1.putExtra("dettagli", "Similar in designed to the Arrow alchemist's fire, this arrow instead carrier an alchemical compound that creates a spray of intense cold.\n" +
" If the arrow strikes a target, the arrow immediately shatters and deals 1d4 points of cold damage.\n");
Arrowalchemistsfrost1.putExtra("Source", "Dragon #349");
startActivity(Arrowalchemistsfrost1);
}
});
}
}
Use tinyDB , you need yo add just one class.
https://github.com/kcochibili/TinyDB--Android-Shared-Preferences-Turbo
Here is code snippet
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ecart);
//Fetch data from DB
GlobaDataHolder.getGlobaDataHolder().setShoppingList(
new TinyDB(getApplicationContext()).getListObject(
PreferenceHelper.MY_CART_LIST_LOCAL, Product.class));
}
#Override
protected void onPause() {
super.onPause();
// Store Shopping Cart in DB
new TinyDB(getApplicationContext()).putListObject(
PreferenceHelper.MY_CART_LIST_LOCAL, GlobaDataHolder
.getGlobaDataHolder().getShoppingList());
}
For complete code refer
https://github.com/hiteshsahu/ECommerce-App-Android/blob/master/app/src/main/java/com/hitesh_sahu/retailapp/view/activities/ECartHomeActivity.java

automatically select first item in list view, and do some other things being called in OnItemClickListener() without having to click

total noob to android and java here.
I found some code on github for connecting a USB GPS device with a u-blox chip. it is here: https://github.com/mikey0000/Ublox-GPS-receiver-android (It took me about 2 days to figure out how to compile this, so yes I am that much of a noob).
I have the device connected in a car android unit, and I'd like it to automatically connect when it boots.
I would like help with automatically selecting the first item in the ListView. I believe the code where this might be do-able is in DeviceListActivity.java:
package com.hoho.android.usbserial.examples;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.TwoLineListItem;
import com.hoho.android.usbserial.driver.CdcAcmSerialDriver;
import com.hoho.android.usbserial.driver.ProbeTable;
import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.hoho.android.usbserial.util.HexDump;
import java.util.ArrayList;
import java.util.List;
import src.com.hoho.android.usbserial.examples.BackgroundService;
/**
* Shows a {#link ListView} of available USB devices.
*
* #author mike wakerly (opensource#hoho.com)
*/
public class DeviceListActivity extends Activity {
private final String TAG = DeviceListActivity.class.getSimpleName();
private UsbManager mUsbManager;
private ListView mListView;
private TextView mProgressBarTitle;
private ProgressBar mProgressBar;
private UsbSerialProber prober;
private static final int MESSAGE_REFRESH = 101;
private static final long REFRESH_TIMEOUT_MILLIS = 5000;
private final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_REFRESH:
refreshDeviceList();
//mHandler.sendEmptyMessageDelayed(MESSAGE_REFRESH, REFRESH_TIMEOUT_MILLIS);
break;
default:
super.handleMessage(msg);
break;
}
}
};
private List<UsbSerialPort> mEntries = new ArrayList<UsbSerialPort>();
private ArrayAdapter<UsbSerialPort> mAdapter;
static class ViewHolder {
TextView textViewItem;
TextView textViewItem2;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
mListView = (ListView) findViewById(R.id.deviceList);
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
mProgressBarTitle = (TextView) findViewById(R.id.progressBarTitle);
ProbeTable customTable = new ProbeTable();
customTable.addProduct(0x1546, 0x01a7, CdcAcmSerialDriver.class);
prober = new UsbSerialProber(customTable);
mAdapter = new ArrayAdapter<UsbSerialPort>(this,
android.R.layout.simple_expandable_list_item_2, mEntries) {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null){
LayoutInflater inflater = (LayoutInflater)getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.two_list_item, null);
holder = new ViewHolder();
holder.textViewItem = (TextView) convertView.findViewById(R.id.text1);
holder.textViewItem2 = (TextView) convertView.findViewById(R.id.text2);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final UsbSerialPort port = mEntries.get(position);
final UsbSerialDriver driver = port.getDriver();
final UsbDevice device = driver.getDevice();
final String title = String.format("Vendor %s Product %s",
HexDump.toHexString((short) device.getVendorId()),
HexDump.toHexString((short) device.getProductId()));
holder.textViewItem.setText(title);
final String subtitle = driver.getClass().getSimpleName();
holder.textViewItem2.setText(subtitle);
return convertView;
}
};
mListView.setAdapter(mAdapter);
mListView.setOnItemClickListener(new ListView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d(TAG, "Pressed item " + position);
if (position >= mEntries.size()) {
Log.w(TAG, "Illegal position.");
return;
}
final UsbSerialPort port = mEntries.get(position);
mHandler.removeMessages(MESSAGE_REFRESH);
showConsoleActivity(port);
}
});
}
#Override
protected void onResume() {
super.onResume();
mHandler.sendEmptyMessage(MESSAGE_REFRESH);
}
#Override
protected void onPause() {
super.onPause();
mHandler.removeMessages(MESSAGE_REFRESH);
}
private void refreshDeviceList() {
showProgressBar();
new AsyncTask<Void, Void, List<UsbSerialPort>>() {
#Override
protected List<UsbSerialPort> doInBackground(Void... params) {
Log.d(TAG, "Refreshing device list ...");
SystemClock.sleep(1000);
final List<UsbSerialDriver> drivers =
prober.findAllDrivers(mUsbManager);
final List<UsbSerialPort> result = new ArrayList<UsbSerialPort>();
for (final UsbSerialDriver driver : drivers) {
final List<UsbSerialPort> ports = driver.getPorts();
Log.d(TAG, String.format("+ %s: %s port%s",
driver, Integer.valueOf(ports.size()), ports.size() == 1 ? "" : "s"));
result.addAll(ports);
}
return result;
}
#Override
protected void onPostExecute(List<UsbSerialPort> result) {
mEntries.clear();
mEntries.addAll(result);
mAdapter.notifyDataSetChanged();
mProgressBarTitle.setText(
String.format("%s device(s) found",Integer.valueOf(mEntries.size())));
hideProgressBar();
Log.d(TAG, "Done refreshing, " + mEntries.size() + " entries found.");
}
}.execute((Void) null);
}
private void showProgressBar() {
mProgressBar.setVisibility(View.VISIBLE);
mProgressBarTitle.setText(R.string.refreshing);
}
private void hideProgressBar() {
mProgressBar.setVisibility(View.INVISIBLE);
}
private void showConsoleActivity(UsbSerialPort port) {
Intent startIntent = new Intent(getApplicationContext(), BackgroundService.class);
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0, startIntent, PendingIntent.FLAG_CANCEL_CURRENT);
mUsbManager.requestPermission(port.getDriver().getDevice(), pendingIntent);
Toast.makeText(this, "Started Background Service for GPS", Toast.LENGTH_LONG).show();
//SerialConsoleActivity.show(this, port);
}
}
Is anyone able to help? I haven't even the first clue where I could go about implementing this. TIA.
EDIT: So it looks like
mListView.setSelection(0);
is the way to go however using
mListView.getSelectedView().setSelected(true);
as well seems to make it crash.
Any idea how I can do the rest of what setOnItemClickListener is doing after automatically selecting the item in the list?
Something like:
mListView.setSelection(0);
final UsbSerialPort port = mEntries.get(0);
mHandler.removeMessages(MESSAGE_REFRESH);
showConsoleActivity(port);
?
Apologies for the earlier ambiguity, but what I wanted this app to do was to do what it does already without me having to tap \ click on anything i.e. on boot automatically select the USB GPS chip that is plugged in so I'd like it not to use the OnItemClickListener or automate that part alternatively. I don't really want the app to sit there waiting for input since the car unit loads all sorts on boot and I keep missing the screen where it prompts as per current behaviour. Hope that's a bit clearer. Thanks for the help so far. Totally new to java and android as you can likely tell haha.
Update: See my answer. Sorry I wasn't clear with my original question. Thanks to everyone for the replies.
You can simply use this setSelection api to true
mListView.setSelection(0);
mListView.getSelectedView().setSelected(true);
for more answers you can check this help, you just need to figure it out where you need to put this code snippet in your code, depending on your needs.
it is very simple:
Array index start from zero so you set selected item from it index like this:
mListView.setSelection(0) ;
and this like put after this line : mListView.setAdapter(mAdapter);
EDIT: Figured it out in the end. I was after a PerformItemClick() - my question was originally ambiguous in setting out what I was trying to do so apologies if anyone lost out on the answer.
Anyway to get this app to automatically choose the connected USB GPS adapter without my having to click on the list I added the following:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
int mActivePosition = 0;
mListView.performItemClick(
mListView.getChildAt(mActivePosition),
mActivePosition,
mListView.getAdapter().getItemId(mActivePosition));
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
//startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
}
}, 2000);
after
mListView.setOnItemClickListener(new ListView.OnItemClickListener() {
and it seemed to do the trick. I also added the intent in there to go to the home page - this seems to help the unit (a car android unit) boot more quickly and call some apps I have configured to load on boot more quickly too.
Thanks to everyone for the answers - sorry I wasn't originally very clear with the question. Hopefully it might be useful for someone.

How can i get hyperlinks text from textview android?

I am working on text-view.in that text-view display html hyperlink.
when i click on hyper-linked text then i want to get that text.
as per above image if i click on hyperlink, then i want to display text.
Your answer would be appreciated
The LinkEnableTextView class is like this:
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.content.Context;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ClickableSpan;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
public class LinkEnabledTextView extends TextView
{
// The String Containing the Text that we have to gather links from private SpannableString linkableText;
// Populating and gathering all the links that are present in the Text
private ArrayList<Hyperlink> listOfLinks;
// A Listener Class for generally sending the Clicks to the one which requires it
TextLinkClickListener mListener;
// Pattern for gathering #usernames from the Text
Pattern screenNamePattern = Pattern.compile('(#[a-zA-Z0-9_]+)');
// Pattern for gathering #hasttags from the Text
Pattern hashTagsPattern = Pattern.compile('(#[a-zA-Z0-9_-]+)');
// Pattern for gathering http:// links from the Text
Pattern hyperLinksPattern = Pattern.compile('([Hh][tT][tT][pP][sS]?:\\/\\/[^ ,'\'>\\]\\)]*[^\\. ,'\'>\\]\\)])');
public LinkEnabledTextView(Context context, AttributeSet attrs)
{
super(context, attrs);
listOfLinks = new ArrayList<Hyperlink>();
}
public void gatherLinksForText(String text)
{
linkableText = new SpannableString(text);
//gatherLinks basically collects the Links depending upon the Pattern that we supply
//and add the links to the ArrayList of the links
gatherLinks(listOfLinks, linkableText, screenNamePattern);
gatherLinks(listOfLinks, linkableText, hashTagsPattern);
gatherLinks(listOfLinks, linkableText, hyperLinksPattern);
for(int i = 0; i< listOfLinks.size(); i++)
{
Hyperlink linkSpec = listOfLinks.get(i);
android.util.Log.v('listOfLinks :: ' + linkSpec.textSpan, 'listOfLinks :: ' + linkSpec.textSpan);
// this process here makes the Clickable Links from the text
linkableText.setSpan(linkSpec.span, linkSpec.start, linkSpec.end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
// sets the text for the TextView with enabled links
setText(linkableText);
}
// sets the Listener for later click propagation purpose
public void setOnTextLinkClickListener(TextLinkClickListener newListener)
{
mListener = newListener;
}
//The Method mainly performs the Regex Comparison for the Pattern and adds them to
//listOfLinks array list
private final void gatherLinks(ArrayList<Hyperlink> links,
Spannable s, Pattern pattern)
{
// Matcher matching the pattern
Matcher m = pattern.matcher(s);
while (m.find())
{
int start = m.start();
int end = m.end();
// Hyperlink is basically used like a structure for storing the information about
// where the link was found.
Hyperlink spec = new Hyperlink();
spec.textSpan = s.subSequence(start, end);
spec.span = new InternalURLSpan(spec.textSpan.toString());
spec.start = start;
spec.end = end;
links.add(spec);
}
}
// This is class which gives us the clicks on the links which we then can use.
public class InternalURLSpan extends ClickableSpan
{
private String clickedSpan;
public InternalURLSpan (String clickedString)
{
clickedSpan = clickedString;
}
#Override
public void onClick(View textView)
{
mListener.onTextLinkClick(textView, clickedSpan);
}
}
// Class for storing the information about the Link Location
class Hyperlink
{
CharSequence textSpan;
InternalURLSpan span;
int start;
int end;
}
Now, having this you require just another interface for propagating the clicks to the place you require to handle them in my case I implemented the interface in my Activity and simple wrote a Log Command there.
The TextLinkClickListener interface is like this:
import android.view.View;
public interface TextLinkClickListener
{
// This method is called when the TextLink is clicked from LinkEnabledTextView
public void onTextLinkClick(View textView, String clickedString)
}
After doing all this you just require to create an Activity using the Custom LinkEnabledTextView and check the things out yourself. There are a few things that you must do while creating a object of the Custom LinkEnabledTextView those are mentioned and described in the Code of the Activity below:
import android.text.method.MovementMethod;
import com.umundoinc.Tvider.Component.LinkEnabledTextView.LinkEnabledTextView;
import com.umundoinc.Tvider.Component.LinkEnabledTextView.TextLinkClickListener;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.view.View;
//Here the Activity is implementing the TextLinkClickListener the one we have created
//the Clicks over the Links are forwarded over here from the LinkEnabledTextView
public class TextViewActivity extends Activity implements TextLinkClickListener
{
private LinkEnabledTextView check;
protected void onCreate(Bundle savedInstance)
{
super.onCreate(savedInstance);
String text = "This is a #test of regular expressions with http://example.com/ links as used in #twitter for performing various operations based on the links this handles multiple links like http://this_is_fun.com/ and #Awesomess and #Cool";
check = new LinkEnabledTextView(this, null);
check.setOnTextLinkClickListener(this);
check.gatherLinksForText(text);
check.setTextColor(Color.WHITE);
check.setLinkTextColor(Color.GREEN);
MovementMethod m = check.getMovementMethod();
if ((m == null) || !(m instanceof LinkMovementMethod)) {
if (check.getLinksClickable()) {
check.setMovementMethod(LinkMovementMethod.getInstance());
}
}
setContentView(check);
}
public void onTextLinkClick(View textView, String clickedString)
{
android.util.Log.v('Hyperlink clicked is :: ' + clickedString, 'Hyperlink clicked is :: ' + clickedString);
}
Hope it will help you!!
Please try my Implementation:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
........
textView mTvTxt = findViewById(R.id.tv_txt_view);
final String hyperlink = "Vasant jetava";
SpannableString spannableString = makeLinkSpan(hyperlink , new View.OnClickListener() {
#Override
public void onClick(View v) {
showDialog(hyperlink)
}
});
mTvTxt.setText(getString("hello whats up man....");
mTvTxt.append(spannableString);
makeLinksFocusable(mTvTxt);
}
private SpannableString makeLinkSpan(CharSequence text, View.OnClickListener listener) {
SpannableString link = new SpannableString(text);
link.setSpan(new ClickableString(listener), 0, text.length(),
SpannableString.SPAN_INCLUSIVE_EXCLUSIVE);
return link;
private void makeLinksFocusable(TextView tv) {
MovementMethod m = tv.getMovementMethod();
if ((m == null) || !(m instanceof LinkMovementMethod)) {
if (tv.getLinksClickable()) {
tv.setMovementMethod(LinkMovementMethod.getInstance());
}
}
}
private static class ClickableString extends ClickableSpan {
private View.OnClickListener mListener;
public ClickableString(View.OnClickListener listener) {
mListener = listener;
}
#Override
public void onClick(View v) {
mListener.onClick(v);
}
}
private void showDialog(String message){
AlertDialog alertDialog = new AlertDialog.Builder(<YourActivityName>this).create(); //Read Update
alertDialog.setTitle("Alert Dialog");
alertDialog.setMessage(message);
alertDialog.setButton("Continue..", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// here you can add functions
}
});
alertDialog.show();
}

Android list view current position doesn't work properly

I'm Getting data from my database and pushing them into ListView to view all the data.
Inside my ListView I also have a TextView with the text "Like" in it. Now when I click the like text it will change to "Liked" and I'm updating my like status in my database.
Now my problem is that when i click the "Like" text, the text changes to "Liked" and also it is updated in DB. But also when I scroll through the List View, I can notice other lists' Like text is also changed to Liked. I'm not sure what's going wrong.
I've been trying to get around this problem for quite some days but had no success.
This is my adapter code. At the bottom you can see my onClickListener for the textview
package com.mytestapp.myapp;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class ForumAdapter extends ArrayAdapter<DiscussionList> {
private static List<DiscussionList> items = null;
public ForumAdapter(Context context, List<DiscussionList> items) {
super(context, R.layout.custom_list, items);
this.items = items;
}
#Override
public int getCount() {
return items.size();
}
public static DiscussionList getModelPosition(int position) {
return items.get(position);
}
public void refill(List<DiscussionList> items) {
items.clear();
items.addAll(items);
notifyDataSetChanged();
}
public static class ViewHolder {
WebView mywebviewholder;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View v = convertView;
if (v == null) {
LayoutInflater li = LayoutInflater.from(getContext());
v = li.inflate(R.layout.custom_list, null);
} else {
holder = (ViewHolder) convertView.getTag();
}
DiscussionList app = items.get(position);
if (app != null) {
TextView titleText = (TextView) v.findViewById(R.id.dscTitle);
TextView categoryText = (TextView) v.findViewById(R.id.dscCategory);
TextView descriptionText = (TextView) v
.findViewById(R.id.dscDescription);
TextView timeText = (TextView) v.findViewById(R.id.dscTime);
TextView idText = (TextView) v.findViewById(R.id.dscDiscId);
final TextView likeText = (TextView) v.findViewById(R.id.likeText1);
String like_Status = app.getLikeStatus();
titleText.setText(app.getTitle());
categoryText.setText(app.getCategory());
descriptionText.setText(app.getDescription());
timeText.setText(app.getTime());
idText.setText(app.getDiscId());
if (like_Status == "null") {
likeText.setText("Like");
} else {
likeText.setText("Liked");
}
final String dId = app.getDiscId();
// onClick for image button inside list view
likeText.setTag(new Integer(position));
likeText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final Integer myposition = (Integer) view.getTag();
// Toast.makeText(getContext(), "" + dId,
// Toast.LENGTH_SHORT)
// .show();
likeText.setText("Liked");
MainActivity val = new MainActivity();
val.updateLikeTable(dId);
}
});
}
return v;
}
}
And also this is my MainActivity.java file where i update the likes in database
package com.mytestapp.myapp;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends ListActivity implements FetchDataListener {
public static String strTitle = "0", strCategory = "0",
strDescription = "0", strTime = "0", strDid = "0";
Collegemate_DB db = new Collegemate_DB(this);
int likeStatus = 1;
private ProgressDialog dialog;
public static String usId=null;
ImageButton imgButton;
List<DiscussionList> items = new ArrayList<DiscussionList>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_forum_topics);
usId = db.getCurrentuserId();
initView();
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
}
/*
* On click listener to get values from DiscussionList class and send it
* to another activity when clicking on the list item
*/
ListView forumList = getListView();
forumList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// Get position of the clicked list item from adapter
String dTitle, dCategory, dDescription, dTime, dDid;
DiscussionList accessVar = ForumAdapter
.getModelPosition(position);
dTitle = accessVar.getTitle();
dCategory = accessVar.getCategory();
dDescription = accessVar.getDescription();
dTime = accessVar.getTime();
dDid = accessVar.getDiscId();
/*
* Storing the forum values in string and passing it to another
* activity
*/
String values[] = { dTitle, dCategory, dDescription, dTime,
dDid };
Intent i = new Intent(MainActivity.this, ForumFullView.class);
i.putExtra("sendData", values);
startActivity(i);
}
});
}
private void initView() {
// show progress dialog
Log.i("j","Inside Init");
dialog = ProgressDialog.show(this, "", "Loading...");
String url = "http://example.com/mypath/listData.php?currentUser_id="
+ usId;
Log.i("Fetch Url : ", url);
FetchDataTask task = new FetchDataTask(this);
task.execute(url);
}
#Override
public void onFetchComplete(List<DiscussionList> data) {
// dismiss the progress dialog
if (dialog != null)
dialog.dismiss();
// create new adapter
ListView forumList = getListView();
// set the adapter to list
ForumAdapter adapter = new ForumAdapter(this, data);
if (forumList.getAdapter() == null) {
//final ForumAdapter adapter = new ForumAdapter(this, data);
forumList.setAdapter(adapter);
} else {
((ForumAdapter) forumList.getAdapter()).refill(items);
}
// setListAdapter(adapter);
}
#Override
public void onFetchFailure(String msg) {
// dismiss the progress dialog
if (dialog != null)
dialog.dismiss();
// show failure message
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
public void updateLikeTable(String dId,List<DiscussionList> items) {
try {
String likeUrl = "http://example.com/mypath/createlike.php?discId="
+ dId + "&userId=" + usId + "&like_status=" + likeStatus;
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet();
request.setURI(new URI(likeUrl));
client.execute(request);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Any help is appreciated.
Thanks in advance
The problem you're having is that the ListView widget recycles its views if it can. Once a view is off the screen from scrolling, it goes onto a garbage heap so that when a new view scrolls into place it can be reused, rather than requiring a fresh one to be inflated from scratch. That recycled view is the convertView parameter in the getView() method. When your ListView is first populating, convertView will always be null, since the garbage pile has nothing in it, so you're forced to inflate new views, but subsequent calls will likely have that parameter as non-null.
The practical result of this is that when a clicked view that's been set to "Liked" gets recycled, the TextView is still there and still populated with "Liked" rather than the presumed default of "Like". So if you click a view, then scroll down so it goes off the screen, it'll come back around and cause the bug you're seeing.
What you'll probably want to do to fix this is to set the text of likeText within getView() every time, based on what it is in your database. If the post has been liked, set it to "Liked", and if it hasn't, set it to "Like". It should just be one more line, assuming you have easy access to whether or not the post is liked from your DiscussionList object.
P.S. As a side note, hard-coded strings are typically frowned upon in Android, so you may want to move your "Liked" string into the resource files. It's not really necessary unless you're planning to do translations, but it's still good practice.

Categories

Resources