Reputation: 163
Im trying to return an ArrayList from the AsyncTask class back to the MainAcitivity class and then use this arraylist to fill the gridview in MainActivity.
The parseURL takes a String paramater to parse the url. And parseURL is executed when the user clicks the button. The code i have compiles and run but the gridview is not populated after triggering the button event and pressing the button twice crashes the app.
EDIT: After adding loop callback, it stops crashing but it still wont populate the gridview. The ArrayList object that i want to populate the gridview is in this format 10,John,Smith
Here is my code for MainActivity (using Stanislav Bodnar suggestion)
private GridView grid1;
private ArrayAdapter<String> adapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//initalized the grid and adapter
grid1 = (GridView)findViewById(R.id.gridView1);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
grid1.setAdapter(adapter);
}
public void onButtonClick(View v) {
EditText textInput = (EditText) findViewById(R.id.editText1);
String code = textInput.getText().toString();
new parseURL() {
@Override
protected void onPostExecute(List<String> list) {
//use the list from parseURL to fill grid view
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
gridView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}.execute(code);
ParseURL class
public class parseURL extends AsyncTask<String, Void, List<String>> {
protected List<String> doInBackground(String... params) {
List<String> str = new ArrayList<String>();
try {
Document doc = Jsoup.connect("http://www.mywebsite.com/id/" + params).get();
Elements row1 = doc.select("table");
Elements row2 = doc.select("td");
Elements row3 = doc.select("td");
for (int i = 0; i < row1.size(); i++) {
str.add(row1.get(i).text() + "," + row2.get(i).text() + "," + row2.get(i).text());
}
return str;
} catch (Exception e) {
return new ArrayList<String>();
}
}
Upvotes: 0
Views: 2348
Reputation: 192
try this:
Mainactivity.class
private GridView grid1;
private ArrayAdapter<String> adapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//initalized the grid and adapter
grid1 = (GridView)findViewById(R.id.gridView1);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
grid1.setAdapter(adapter);
}
public void onButtonClick(View v) {
EditText textInput = (EditText) findViewById(R.id.editText1);
String code = textInput.getText().toString();
new parseURL(this).execute(code);
}
public void onBackgroundTaskCompleted(List<String> result) {
// TODO Auto-generated method stub
Log.i(TAG, "onBackgroundTaskCompleted List: "+result);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
gridView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
Asynctask:
public class parseURL extends AsyncTask<String, Void, List<String>> {
MainActivity caller;
public Scheduler(MainActivity mainActivity) {
// TODO Auto-generated constructor stub
this.caller = mainActivity;
}
protected void onPostExecute(List<String> result) {
caller.onBackgroundTaskCompleted(result);
}
protected List<String> doInBackground(String... params) {
List<String> str = new ArrayList<String>();
try {
Document doc = Jsoup.connect("http://www.mywebsite.com/id/" + params).get();
Elements row1 = doc.select("table");
Elements row2 = doc.select("td");
Elements row3 = doc.select("td");
for (int i = 0; i < row1.size(); i++) {
str.add(row1.get(i).text() + "," + row2.get(i).text() + "," + row2.get(i).text());
}
return str;
} catch (Exception e) {
return new ArrayList<String>();
}
}
}
Upvotes: 1
Reputation: 3021
Don't do gridview.setAdapter()
twice. There are a few problems with that code. As P-a Bäckström wrote:
Also, passing around the MainActivity feels a bit shaky. What happens if the Activity is destroyed during the async-task? Instead, make the AsyncTask a private inner class or an anonymous class in MainActivity
You need to fix that too. Now comes the updating part:
Declare a global Handler like this:
private final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if(msg.what == 1) {
List<String> list = (List) msg.obj;
adapter.insert(list);
adapter.notifyDataSetChanged();
}
}
};
Then in onPostExecute()
send your data to the UI thread using the handler and update the gridview:
protected void onPostExecute(List<String> list) {
handler.obtainMessage(1, list);
}
Upvotes: 1
Reputation: 385
You can add loading callback.
public void onButtonClick(View v) {
EditText textInput = (EditText) findViewById(R.id.editText1);
String code = textInput.getText().toString();
new parseURL() {
@Override
protected void onPostExecute(List<String> list) {
//use the list from parseURL to fill grid view
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
gridView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}.execute(code);
}
Asynctask:
public class parseURL extends AsyncTask<String, Void, List<String>> {
protected List<String> doInBackground(String... params) {
List<String> str = new ArrayList<String>();
try {
Document doc = Jsoup.connect("http://www.mywebsite.com/id/" + params).get();
Elements row1 = doc.select("table");
Elements row2 = doc.select("td");
Elements row3 = doc.select("td");
for (int i = 0; i < row1.size(); i++) {
str.add(row1.get(i).text() + "," + row2.get(i).text() + "," + row2.get(i).text());
}
return str;
} catch (Exception e) {
return new ArrayList<String>();
}
}
}
Supplement
If array list that returns by onPostExecute is not empty your grid will be populated in the next way each cell will have string 10,John,Smith. Please check that method doInBackground does not catch some exception and fills array list correctly.
Next if you want to do a table view where 1 row will contain 3 columns 10 | John | Smith then parse data into object structure:
class Person {
private int id;
private String firstName;
private String lastName;
}
Then change method doInBackground to return array list of Person objects.
Create custom adapter (extend BaseAdapter) where init view using Person object. View will be as LinearLayout with horizontal orientation which will contain 3 TextView with Layout Weight (android:layout_weight="0.3" - set in each TextView, you can change this value). Then use ListView instead of GridView. Each row of list view will contain 1 Person.
Upvotes: 1
Reputation: 529
The AsyncTask is by definition asynchronous. Your code handles it like it was synchronous.
Move
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
gridView.setAdapter(adapter);
adapter.notifyDataSetChanged();
into the setList method.
Also, passing around the MainActivity feels a bit shaky. What happens if the Activity is destroyed during the async-task? Instead, make the AsyncTask a private inner class or an anonymous class in MainActivity
And of course you will need to initialize your list before you populate it.
Upvotes: 1