I have two classes,HomeActivity and CustomListAdapter.THe HomeActivity class extends an activity and then updates a listview.I am populating the data to the listview using a CustomListAdapter class which extends BaseAsapter.Everything is working fine but i want to load the data in a background task.When i do that,an error comes up.
Here is my implementation of the onPostExecute of the AyncTask class.
#Override
protected void onPostExecute(HomeActivity Params){
progressDialog.dismiss();
runOnUiThread(new Runnable(){
public void run(){
final ListView lv1 = (ListView) findViewById(R.id.listings);
lv1.setAdapter(new CustomListAdapter(this, shares));
}
});
}
I get an error telling me that i should change the constructor on CustomListAdapter.But when i change it,everything goes downhill.
I have tried this unsuccessfully too
final ListView lv1 = (ListView) findViewById(R.id.listings);
lv1.setAdapter(new CustomListAdapter(this, shares));
shares is an arraylist of data from the web service.
Here is the constructor in the CustomListAdapter class
public CustomListAdapter(Context context, ArrayList listData) {
this.listData = listData;
layoutInflater = LayoutInflater.from(context);
}
How can go about it?Help will be highly appreciated.
You have to change :
#Override
protected void onPostExecute(HomeActivity Params){
progressDialog.dismiss();
runOnUiThread(new Runnable(){
public void run(){
final ListView lv1 = (ListView) findViewById(R.id.listings);
lv1.setAdapter(new CustomListAdapter(YourActivity.this, shares));
}
});
}
See the below code works for me
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
progressDilaog.dismiss();
itemListAdapter = new ItemListBaseAdapter(
IncidentListActivity.this, Util.arrIncidents);
gridView.setAdapter(itemListAdapter);
}
And one more thing, you don't require runOnUiThread in onPostExecute method. You can directly change your listview.
You are sending your AsyncTask context to your Adapter , you should put your Activity context which hosts your Listview to your AsyncTask class then use that Context to construct your Adapter.
Edit : look at this as an example and onPostExecute by default runs on Ui thread and it doesn't need to define a runOnUiThread
public class SyncHandler extends AsyncTask<String, Void, ResponseType>{
private Activity activity;
public SyncHandler (Activity activity)
{
this.activity = activity;
}
then in your calling Activity pass the Activity context to your Async class :
new SyncHandler(this).execute();
Related
Initially, after setting up custom listview, no more items are getting added i.e displayed in list view inspite of adding Object item from FirebaseMessagingService.
I have declared listView static so that Object can be added to the list from other classes or services.
Here's my code:
FirebaseMessagingService:
#Override
public void onMessageReceived(final RemoteMessage remoteMessage) {
//Toast.makeText(getApplicationContext(), remoteMessage.getData().get("transaction"),Toast.LENGTH_SHORT).show();
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Gson gson = new Gson();
Block b = gson.fromJson(remoteMessage.getData().get("transaction"), Block.class);
OpenChain.arrayList.add(b);
}
});
}
ListView activity code:
public static ArrayList<Block> arrayList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_open_chain);
arrayList = new ArrayList<>();
getSupportActionBar().setTitle("Vote Ledger");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ListView listView = (ListView) findViewById(R.id.listView);
BlockchainAdap adap = new BlockchainAdap(this, arrayList);
listView.setAdapter(adap);
adap.notifyDataSetChanged();
}
**I am receiving object from cloud in json format
**Also able to add objects from within listview activity but not from FirebaseMessagingSerivce
I have declared listView static so that Object can be added to the
list from other classes or services.
Not, a good solution, you are leaking arrayList here, as it wont be garbage collected when activity gets destroyed.
A better approach would be to use LocalBroadCast in this scenario.
Checkout the link for info
https://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html
Now, what you are doing wrong. You, are modifying the arraylist but you are not notifying the adapter about the same.
Try this..
private ArrayList<Block> arrayList = new ArrayList<>();
private BlockchainAdap adap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_open_chain);
getSupportActionBar().setTitle("Vote Ledger");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ListView listView = (ListView) findViewById(R.id.listView);
adap = new BlockchainAdap(this, arrayList);
listView.setAdapter(adap);
}
public static void updateList(Block b){
arrayList.add(b);
adap.swap(arrayList);
}
In FirebaseMessagingService
#Override
public void onMessageReceived(final RemoteMessage remoteMessage) {
Gson gson = new Gson();
Block b = gson.fromJson(remoteMessage.getData().get("transaction"), Block.class);
OpenChain.updateList(b);
}
Also, expose a method in your ** BlockchainAdap** for swap.
class BlockchainAdap {
ArrayList<Block> arrayList;
BlockchainAdap(ArrayList<Block> arrayList){
this.arrayList = arrayList;
}
public void swap(ArrayList<Block> arrayList){
this.arrayList = arrayList;
notifydatasetChanged();
}
// other methods
}
This will work, but use
LocalBroadcastReceiver from messaging service to OpenChain activity.
Use RecyclerView instead of ListView.
I wanna add items to my list but it only shows the first one:
public class MainActivity extends Activity {
Server server;
TextView infoip, msg;
TextView usersTitle;
String[] array = {"a"};
ArrayList<String> lst;
ArrayAdapter<String> adapter;
ListView userList;
#Override
public void onCreate(Bundle savedInstanceState) {
lst = new ArrayList<String>(Arrays.asList(array));
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, lst);
userList = (ListView) findViewById(R.id.userList);
userList.setAdapter(adapter);
From this other class method, everytime it is called I want the text to go below the first one. The method certainly runs but it does not put the text below the previous one. It just shows "a"! Anyone knows why?
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
activity.lst.add(message);
activity.adapter.notifyDataSetChanged();
}
});
I have also tried:
adapter.insert(String, int);
lst.add(int, String);
And even added in the onCreate method this:
lst.add(1, "2");
adapter.notifyDataSetChanged();
And still doesnt add the "2"!!
If you are adding items to Arraylist from another class ,you have to declare your Arraylist Static.So that it can hold items in memory.
Replace ArrayList lst with public static ArrayList
Here is the solution to your Problem.I have created an Activity class and Tests java class.
public class MainActivity extends Activity {
String[] array = {"a"};
public static ArrayList<String> lst;
ArrayAdapter<String> adapter;
ListView userList;
Tests tests = new Tests();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
userList = (ListView) findViewById(R.id.userList);
lst = new ArrayList<String>(Arrays.asList(array));
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, lst);
userList.setAdapter(adapter);
tests.callThread();
}
}
Here is the Tests.java Class
public class Tests {
int i = 0;
String message = "";
Thread runOnUiThread;
public void callThread()
{
new Thread(new Runnable() {
#Override
public void run() {
try {
while (i < 10) {
i = i + 1;
message = String.valueOf(i);
//Create a server socket object and bind it to a port
MainActivity.lst.add(message);
}
}catch(Exception e){
e.printStackTrace();
}
}
}).start();
}
}
Just call your service inside this thread where I have incremented variable i and by this way you can populate the list in right order.
Can you tell whether the other class is Activity or Fragment ?
And while adding the data into Arraylist, you don't need the Thread to be run in order to insert new data to Arraylist
Try to make "lst" and "adapter" both static.
I'm suspicious about the runOnUiThread. Can you provide more information why did you use this function? Also i highly recommend using RecyclerView
Also you can refer to this post for adding items to RecyclerView
i have an AsyncTask where in "doinbackground", it update the variable "pics", later in postexecute i update all, the problem is than i wanna update the adapter when i'm updating the varible "pics". where i should declare the adapter, and call notifyDataSetChanged??
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all products
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed JSON data into ListView
* */
mAdapter = new Gridadapter(tab.this, pics);
gridView.setAdapter(mAdapter);
}
});
thx!
you don't need to call the runOnUiThread(...) inside the onPostExecute. that method is already called inside the UI thread.
the adapter can be declared when you declare the other components of the views and you should use always the same instance. (dont create a new adapter every time you have an update do do!)
I would create an adapter like that:
public class GridAdapter extends BaseAdapter{
private ArrayList<Items> mItemList;
public void updateItemList(ArrayList<Items> newItemList){
this.mItemList = newItemList;
notifyDataSetChanged();
}
}
then instance it:
public void onCreate(Bundle savedInstance){
// ...all the previous code
mGridView = (GridView) findViewById(R.id.gridview);
mGridAdapter = new GridAdapter(this);
mGridView.setAdapter(mGridAdapter);
}
and call the update from the onPostExecute:
protected void onPostExecute(String file_url) {
mGridAdapter.updateItemList(pics);
}
I'm using SherlockListFragment(whichis the same as ListFragment) for displaying sms conversation list
Here is the code
public static class TitlesFragment extends SherlockListFragment
{
static ConversationAdapter adapter;
static List<String> msgList;
static Activity activity;
static ListView listView;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
DataGetters dataGetters = new DataGetters();
activity = getActivity();
msgList = dataGetters.getCONVERSATIONS(activity.getApplicationContext());
adapter = new ConversationAdapter(activity, msgList);
setListAdapter(adapter);
}
Code above prints all current sms conversations
like this:
I'm refreshing adapter from code below by calling adapter.notifyDataSetChanged(); witch is called when new sms is received
public class ReceiverClass extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
Thread.sleep(2000);
return null;
}
#Override
protected void onPostExecute(String result) {
TitlesFragment.adapter.notifyDataSetChanged();
}
But fallowing code overides existing list view items insted of adding new list item position like this:
When i activity is recreated i get what i want but only then: example:
You are most likely incorrectly modifying the List that the ListAdapter is attached to.
So the problem was not me not modifiy adpater list with new position
Here is the code that neded to be added
msgList= dataGetters.getCONVERSATIONS(activity.getApplicationContext());
ConversationAdapter.msgList = msgList;
TitlesFragment.adapter.notifyDataSetChanged();
Solved thanks to Mark Nguyen
I'm a noob to android development and i am trying to show a progressbar while i populate a listview during onCreate. I am trying to use a custom adapter, but eclipse is saying that my constructor is undefined. Specifically, "The constructor MainActivity.UserItemAdapter(new Thread(){}, int, ArrayList) is undefined" It suggests that i change the context parameter on my custom adapter to thread. Ideally, i would like to resolve this without having to change my constructor, because i use it elsewhere in my code. Any help is greatly appreciated. Here is my code.
On Create:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
dialog = ProgressDialog.show(MainActivity.this, "Loading", "Loading, please wait..");
Thread t = new Thread() {
public void run() {
//getting data for listview...
ListView listView = (ListView) findViewById(R.id.ListViewId);
listView.setAdapter(new UserItemAdapter(this, R.layout.listitem, tweets));//<--error here constructor is undefined.
handler.post(new Runnable() {
public void run() {
dialog.dismiss();
};
});
}
};
t.start();
}
My Custom Adapter:
public class UserItemAdapter extends ArrayAdapter<Tweet> {
private ArrayList<Tweet> tweets;
public UserItemAdapter(Context context, int textViewResourceId, ArrayList<Tweet> tweets) {
super(context, textViewResourceId, tweets);
this.tweets = tweets;
}
this refers to the Thread object in that case. User either getApplicationContext() or MyActivity.this.