AsyncTask onPostExecute TextView not updating - java

My situation is like this:
My main activity has 3 fragments. The first fragment requests data from the server and tries to render it. I use an AsyncTask inner class to get the data and render in onPostExecute. I render using a SimpleCursorAdapter with a ListView. Rendering works fine. After this is done, I try to manipulate the UI (set value of a TextView) but it is not working. getViewById does not return null or any errors but I still cannot change the value for some reason. Any suggestions are highly appreciated. Here is the Fragment Class that I use:
public class FeedFragment extends Fragment {
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_feed, container, false);
Activity activity = getActivity();
try {
new getFeedData(activity,rootView).execute();
}
finally{
return rootView;
}
}
private class getFeedData extends AsyncTask<Void, Void, String> {
private Context activity;
private View rootView;
public getFeedData(Context context, View main){
this.activity=context;
this.rootView=main;
}
#Override
protected String doInBackground(Void... params) {
try {
HttpRequest request = HttpRequest.get("http://upinion.us/test/feed_sample/");
String response = "";
if (request.ok()) {
response = request.body();
}
return response;
} catch (HttpRequestException exception) {
return null;
}
}
#Override
protected void onPostExecute(String response) {
String[] columns = new String[] {"_id","title","description"};
int[] viewIds = new int[] {R.id.postId,R.id.title,R.id.description};
JSONArray finalResponse;
try {
finalResponse = new JSONArray(response);
} catch (JSONException e) {
e.printStackTrace();
finalResponse = null;
}
MatrixCursor mc = new MatrixCursor(new String[] {"_id","title","description"}); // properties from the JSONObjects
for (int i = 0; i < finalResponse.length(); i++) {
JSONObject jsonObject;
try {
jsonObject = finalResponse.getJSONObject(i);
mc.addRow(new Object[] {jsonObject.get("_id"),jsonObject.get("title"),jsonObject.get("description")});
} catch (JSONException e) {
jsonObject=null;
}
}
SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(getActivity(), R.layout.post, mc, columns, viewIds,0);
ListView list = (ListView) this.rootView.findViewById(R.id.feed_feed);
list.setAdapter(mAdapter);
View v;
for (int i = 0; i < list.getCount(); i++) {
v = list.getAdapter().getView(i, null, null);
TextView text = (TextView) v.findViewById(R.id.title);
text.setText("HELLO MOTO");
}
list.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// selected item
Integer convId = parent.getId();
}
});
}
}
}
As you can see, I pass the activity and the inflated root view to the asynctask, but still no luck. I have spent nearly two days trying to find a solution with no success.

for (int i = 0; i < list.getCount(); i++) {
v = list.getAdapter().getView(i, null, null);
TextView text = (TextView) v.findViewById(R.id.title);
text.setText("HELLO MOTO");
}
this is your problem:
you are NOT supposed to call getView yourself
to update your listview, you need to call adapter.notifyDataSetChanged
and the system will call the updates for you
so remove this piece of code entirely and just replace it with adapter.notifyDataSetChanged

Related

Can't add data from json in ArrayList

I'm trying to display data from JSON in listView, but whenever I'll try to add some value from json, my list shows me nothing.
Activity
public static final String LOG = hourlyWeather.class.getSimpleName();
double test;
RequestQueue mQuene;
ArrayList<Weather> list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hourly_weather);
mQuene = Volley.newRequestQueue(this);
list = new ArrayList<Weather>();
test();
hourlyWeatherAdapter adapter = new hourlyWeatherAdapter(this, list);
ListView listView = (ListView) findViewById(R.id.weatherListView);
listView.setAdapter(adapter);
}
public void test() {
String url = "https://api.openweathermap.org/data/2.5/weather?lat=50.7578594&lon=16.2127653&units=metric&appid=ID";
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
response -> {
try {
JSONObject object = response.getJSONObject("main");
for (int i = 0; i<object.length(); i++){
test = object.getDouble("temp");
}
Log.i(LOG,String.valueOf(test));
list.add(new Weather(test));
} catch (JSONException e) {
e.printStackTrace();
}
}, Throwable::printStackTrace);
mQuene.add(request);
}
}
Adapter
public class hourlyWeatherAdapter extends ArrayAdapter<Weather> {
public hourlyWeatherAdapter(#NonNull Context context, ArrayList<Weather> list) {
super(context, 0, list);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View view = convertView;
if (view == null) {
view = LayoutInflater.from(getContext()).inflate(R.layout.weather_list_item, parent, false);
}
Weather model = getItem(position);
TextView temperature = (TextView) view.findViewById(R.id.hourly_time);
temperature.append(String.valueOf(model.getTemp()));
return view;
}
}
public class Weather {
private double temp;
public Weather(double temp) {
this.temp = temp;
}
public double getTemp() {
return temp;
}
}
When I'll using the Log.i, I can clearly see value from json in my logcat. Where can be issue? I've tried to add some dummy data, and it works out just fine.
You must declare hourlyWeatherAdapter adapter = new hourlyWeatherAdapter(this, list); outside your onCreate() method, and after change your array, you must call notifyDataSetChanged();. Also, you must initialize your list and adapter before call test().
public static final String LOG = hourlyWeather.class.getSimpleName();
double test;
RequestQueue mQuene;
ArrayList<Weather> list;
hourlyWeatherAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hourly_weather);
mQuene = Volley.newRequestQueue(this);
list = new ArrayList<Weather>();
adapter = new hourlyWeatherAdapter(this, list);
ListView listView = (ListView) findViewById(R.id.weatherListView);
listView.setAdapter(adapter);
test();
}
public void test() {
String url = "https://api.openweathermap.org/data/2.5/weather?lat=50.7578594&lon=16.2127653&units=metric&appid=ID";
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
response -> {
try {
JSONObject object = response.getJSONObject("main");
for (int i = 0; i<object.length(); i++){
test = object.getDouble("temp");
}
Log.i(LOG,String.valueOf(test));
list.add(new Weather(test));
// Update list
adapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}, Throwable::printStackTrace);
mQuene.add(request);
}
}

Integrating Loaders and recycler view not working

I am using a loader and a OkHttp client to get data from a news API and populate the data in a recycler view. I used a progress bar to show until the the loader is finished loading the data . But all I see is the progress bar, the recycler view is not showing up.
Please help me
MainActivity.java
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<ArrayList<News>> {
private static final int LOADER_ID = 1 ;
private String url = "https://newsapi.org/v1/articles?source=the-times-of-india&sortBy=latest&apiKey=<API KEY>";
private ProgressBar progressBar;
private NewsAdapter mAdapter;
private RecyclerView recList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar) findViewById(R.id.progress_bar);
progressBar.setVisibility(View.VISIBLE);
recList = (RecyclerView) findViewById(R.id.cardList);
recList.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(this);
llm.setOrientation(LinearLayoutManager.VERTICAL);
recList.setLayoutManager(llm);
recList.setHasFixedSize(true);
getSupportLoaderManager().initLoader(LOADER_ID , null , this);
}
#Override
public Loader<ArrayList<News>> onCreateLoader(int id, Bundle args) {
return new AsyncTaskLoader<ArrayList<News>>(this) {
#Override
public ArrayList<News> loadInBackground() {
return makeConnectionAndParseData(url);
}
};
}
#Override
public void onLoadFinished(Loader<ArrayList<News>> loader, ArrayList<News> data) {
progressBar.setVisibility(View.INVISIBLE);
mAdapter = new NewsAdapter(data);
recList.setAdapter(mAdapter);
// The data is brought back here after the network call is executed in the variable data.
// Update the recycler view here to show the list of news
// Take care of exception cases like no network connection , invalid url and other extreme cases
}
#Override
public void onLoaderReset(Loader<ArrayList<News>> loader) {
// Reset the recycler view . The UI should not show recycler view when the loader is reset
// Update the UI with a text view to let the user know about the error
}
private String makeNetworkConnection(String url)
{
OkHttpClient client = new OkHttpClient();
try {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().toString();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private ArrayList<News> parseJsonIntoArrayList(String json)
{
final ArrayList<News> newsArrayList;
try {
newsArrayList = null;
JSONObject object = new JSONObject(json);
JSONArray articles = object.getJSONArray("articles");
for (int i=0 ; i<articles.length() ; i++)
{
JSONObject articleObjects = articles.getJSONObject(i);
String author = articleObjects.getString("author");
String title = articleObjects.getString("title");
String desc = articleObjects.getString("description");
String imageUrl = articleObjects.getString("imageUrl");
String clickableUrl = articleObjects.getString("url");
newsArrayList.add(new News(title,desc,imageUrl,clickableUrl,author));
}
return newsArrayList;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
private ArrayList<News> makeConnectionAndParseData(String url)
{
String jsonResponse = makeNetworkConnection(url);
return parseJsonIntoArrayList(jsonResponse);
}}
NewsAdapter.java
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.NewsHolder> {
ArrayList<News> mNewsData;
public NewsAdapter(ArrayList<News> newsData)
{
mNewsData = newsData;
}
public class NewsHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView titleTv , descTv ;
private ImageView newsImageView;
public NewsHolder(View itemView) {
super(itemView);
titleTv = (TextView) itemView.findViewById(R.id.newsTitle);
descTv = (TextView) itemView.findViewById(R.id.newsDesc);
newsImageView = (ImageView) itemView.findViewById(R.id.newsImage);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
// Handle the click item here.
}
}
#Override
public NewsHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View inflatedView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item , parent , false);
return new NewsHolder(inflatedView);
}
#Override
public void onBindViewHolder(NewsHolder holder, int position) {
News news = mNewsData.get(position);
holder.titleTv.setText(news.getNewsTitle());
holder.descTv.setText(news.getNewsSubtitle());
String imageUrl = news.getImageUrl();
Picasso.with(holder.newsImageView.getContext())
.load(imageUrl)
.into(holder.newsImageView);
}
#Override
public int getItemCount() {
return mNewsData.size();
}}
In android monitor , there was
01-10 14:55:59.319 10318-10318/com.sriram.news E/RecyclerView: No adapter attached; skipping layout
Please tell me where I have gone wrong
And is my implementation of the recycler view correct? I'm still confused about recycler view.
Thanks in advance
Place
mAdapter = new NewsAdapter();
recList.setAdapter(mAdapter);
above
recList.setLayoutManager(llm);
recList.setHasFixedSize(true);
and fix NewsAdapter.java
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.NewsHolder> {
ArrayList<News> mNewsData;
// remove constructor
public void addAll(List<News> newsData) {
mNewsData = newsData;
}
...
}
MainActivity.java
#Override
public void onLoadFinished(Loader<ArrayList<News>> loader, ArrayList<News> data) {
progressBar.setVisibility(View.INVISIBLE);
mAdapter.addAll(data);
mAdapter.notifyDataSetChanged();
}

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!!!

Creating dynamic ListView using BaseAdapter class not working

I am trying to create a dynamic List View using BaseAdapter class.
Below is the code that I am using here.
Code for Main Activity:
public class DisplayFlightsActivity extends AppCompatActivity {
String str_jsonresponse,fare,carrier,number,arrivaltime,departuretime,origin,destination;
ArrayList<String> listitem = new ArrayList<String>();
ListView listView;
//MyBaseAdapter baseAdapter;
Context context = DisplayFlightsActivity.this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
Bundle extras = intent.getExtras();
str_jsonresponse = extras.getString(DisplaySummaryActivity.STR_JSONRESPONSE);
try{
JSONObject root_jsonresponse = new JSONObject(str_jsonresponse);
JSONObject l1_jsonobject = root_jsonresponse.optJSONObject("trips");
JSONArray l2_jsonarray = l1_jsonobject.optJSONArray("tripOption");
for (int i=0;i < l2_jsonarray.length();i++)
{
JSONObject l21_jsonobject = l2_jsonarray.getJSONObject(i);
fare = l21_jsonobject.getString("saleTotal");
JSONArray l3_jsonarray = l21_jsonobject.optJSONArray("slice");
for (int j=0;j < l3_jsonarray.length();j++)
{
JSONObject l4_jsonobject = l3_jsonarray.getJSONObject(j);
JSONArray l5_jsonarray = l4_jsonobject.optJSONArray("segment");
for(int k=0;k < l5_jsonarray.length();k++)
{
JSONObject l6_jsonobject = l5_jsonarray.getJSONObject(k);
JSONObject l7_jsonobject = l6_jsonobject.optJSONObject("flight");
carrier = l7_jsonobject.getString("carrier");
number = l7_jsonobject.getString("number");
JSONArray l8_jsonarray = l6_jsonobject.optJSONArray("leg");
for(int m=0;m < l8_jsonarray.length(); m++)
{
JSONObject l9_jsonobject = l8_jsonarray.getJSONObject(m);
arrivaltime = l9_jsonobject.getString("arrivalTime");
departuretime = l9_jsonobject.getString("departureTime");
origin = l9_jsonobject.getString("origin");
destination = l9_jsonobject.getString("destination");
}
}
}
listitem.add(fare);
listitem.add(carrier);
listitem.add(number);
listitem.add(arrivaltime);
listitem.add(departuretime);
listitem.add(origin);
listitem.add(destination);
}
}
catch(JSONException JE){
JE.printStackTrace();
}
catch (Exception err){
err.printStackTrace();
}
MyBaseAdapter baseAdapter = new MyBaseAdapter(context,listitem);
listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(baseAdapter);
setTitle("Results Page");
//setContentView(R.layout.activity_display_flights);
}
}
Code for Base Adapter class:
class MyBaseAdapter extends BaseAdapter {
Context context;
ArrayList<String> listitem = new ArrayList<>();
LayoutInflater inflater = null;
public MyBaseAdapter(Context context, ArrayList<String> listitem) {
this.context = context;
this.listitem = listitem;
inflater = LayoutInflater.from(this.context);
}
public int getCount() {
return listitem.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
if (convertView == null)
vi = inflater.inflate(R.layout.listview_item_layout, null);
TextView carrier = (TextView) vi.findViewById(R.id.layout_textview1);
TextView number = (TextView) vi.findViewById(R.id.layout_textview2);
TextView arrivaltime = (TextView) vi.findViewById(R.id.layout_textview6);
TextView departuretime = (TextView) vi.findViewById(R.id.layout_textview7);
TextView saletotal = (TextView) vi.findViewById(R.id.layout_textview8);
String str_carrier = listitem.get(position).toString();
String str_number = listitem.get(position).toString();
String str_arrivaltime = listitem.get(position).toString();
String str_departuretime = listitem.get(position).toString();
String str_saletotal = listitem.get(position).toString();
carrier.setText(str_carrier);
number.setText(str_number);
arrivaltime.setText(str_arrivaltime);
departuretime.setText(str_departuretime);
saletotal.setText(str_saletotal);
return vi;
}
}
My Problem is: The Base Adapter class is never getting invoked for me. I was trying to debug, but the control never goes inside of BaseAdapter class. I am able to parse the JSON Data and put it in ListItem but I am not able to access Base Adapter class.
Is there anything I am doing wrong? Can anybody please review the code and let me know why it is not working.
Thanks in advance!
I was able to solve the problem by adding the line setContentView(R.layout.activity_display_flights); above, like this --
baseAdapter = new MyBaseAdapter(context,listitem);
setTitle("Results Page");
setContentView(R.layout.activity_display_flights);
listView = (ListView) findViewById(R.id.list_view);
listView.setBackgroundResource(R.drawable.androidbckgrnd1);
listView.setAdapter(baseAdapter);
Earlier the ListView instance was coming as null. Now that issue has been resolved.

getItem(position) Android issue

I created a custom adapter for a ListView with a CheckBox in each row. Each time I check a Checkbox, I want to trigger an action on the selected item in my ListView, but the getItem(position) always return the last item in the ListView.
Set the adapter:
public void onPostExecuteSearchRequestedCars(JSONArray array){
List<JSONObject> list = new ArrayList<>(array.length());
try {
for(int i = 0 ; i < array.length() ; i++){
JSONObject temp = array.getJSONObject(i);
list.add(temp);
}
} catch (JSONException e) {
Log.e(e.getClass().getName(),"There is no JSONObject in the JSONArray", e);
}
// Create and set the custom listView.
adapter = new CustomSpecificCar(this, list, this);
lv = (ListView) findViewById(R.id.lvCars);
lv.setAdapter(adapter);
}
Custom Adapter:
public class CustomSpecificCar extends ArrayAdapter<JSONObject>{
ListSpecificCars caller;
private JSONObject currentJson;
private CheckBox cbSelectedCar;
private List<JSONObject> list;
public CustomSpecificCar(Context ctxt, List<JSONObject> list, ListSpecificCars caller){
super(ctxt, R.layout.custom_specific_car_row, list);
this.caller = caller;
this.list = list;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(getContext());
final View customView = inflater.inflate(R.layout.custom_specific_car_row, parent, false);
// Set the reference of the layout
currentJson = caller.getItem(position);
cbSelectedCar = (CheckBox)customView.findViewById(R.id.cbSelectedCar);
TextView tvBrand = (TextView)customView.findViewById(R.id.tvBrand);
TextView tvModel = (TextView)customView.findViewById(R.id.tvModel);
TextView tvOwnerEditable = (TextView)customView.findViewById(R.id.tvOwnerEditable);
TextView tvPriceEditable = (TextView)customView.findViewById(R.id.tvEstimatedPriceEditable);
try {
tvBrand.setText(currentJson.getString("brand"));
tvModel.setText(currentJson.getString("model"));
tvOwnerEditable.setText(currentJson.getString("owner"));
} catch (JSONException e) {
Log.e(e.getClass().getName(), "JSONException", e);
}
cbSelectedCar.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
caller.updateClickedUsername(currentJson, true); // Add to the List
try {
Log.d("Has been checked ", currentJson.getString("brand"));
} catch (JSONException e) {
e.printStackTrace();
}
}
else
caller.updateClickedUsername(currentJson, false); // Delete from the List
}
});
return customView;
}
#Override
public int getCount() {
return list.size();
}
}
EDIT
I added a getItem in my caller class:
public JSONObject getItem(int position){
return list.get(position);
}
I suspect the error is this one: I call getView() each time a JSONObject is added to the list and set the value of this object in the global variables. (private JSONObject currentJson).
Can you put me on the right way?
EDIT 2
Finally achieved it, by using each and every time getItem(position) instead of currentJson.
Please try using
caller.getItem(position)
and override getCount.
#Override
public int getCount() {
return (caller== null) ? 0 : caller.size();
}

Categories

Resources