Reputation: 97
I need to get text from a website which is done in a new thread. Then i need to put that text in a list view. The problem is that i cant set up array adapter for list view until text is put in the lists used in that adapter. Lists are filled in that thread used for connecting to website.
I tried to solve that by setting up adapter in new thread run by first thread. Program starts without errors, but nothing shows up in list view.
I am using List view code from this site http://www.vogella.com/articles/AndroidListView/article.html
Im a newbie in java and android so i hope you understand what im trying to do :)
Heres the code
package com.example.studentservis;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.R.string;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.Menu;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
public class MainActivity extends Activity {
String s;
List<String> headersList = new ArrayList<String>();
List<String> contentList = new ArrayList<String>();
ListView listview;
StableArrayAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listview = (ListView) findViewById(R.id.listView1);
threadStart();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public void adapterInit()
{
adapter = new StableArrayAdapter(this, android.R.layout.simple_list_item_1, headersList);
listview.setAdapter(adapter);
}
private class StableArrayAdapter extends ArrayAdapter<String>{
HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();
public StableArrayAdapter(Context context, int textViewResourceId,
List<String> objects) {
super(context, textViewResourceId, objects);
// TODO Auto-generated constructor stub
for (int i = 0; i < objects.size(); ++i) {
mIdMap.put(objects.get(i), i);
}
}
@Override
public long getItemId(int position) {
String item = getItem(position);
return mIdMap.get(item);
}
@Override
public boolean hasStableIds() {
return true;
}
}
public void threadStart()
{
//txtView.setText(stringHandler.getString());
new Thread(new Runnable() { // thread
public void run(){
try
{
webRequest();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new Runnable()
{
@Override
public void run() {
// TODO Auto-generated method stub
adapterInit();
}
};
}
}).start();
}
public void webRequest() throws Exception{
String servisURL = "http://www.sczg.unizg.hr/student-servis/";
Document doc = Jsoup.connect(servisURL).get();
Elements jobNode = doc.select("div.jobBox");
Elements headersNode = jobNode.select("h1");
Elements contentNode = jobNode.select("content");
for(int i = 0; i < headersNode.size(); i++){
headersList.add(headersNode.get(i).text());
}
for(int i = 0; i < contentNode.size(); i++){
contentList.add(contentNode.get(i).text());
}
}
}
Upvotes: 1
Views: 775
Reputation: 29
You can use Handler. In the webRequest thread,When webRequest() finished,you use Handler to notice the main thread to adapterInit().Not use another thread in the webRequest thread. A simple example.
@Override
public void onClick(DialogInterface dialog,
int which) {
setControlsEnable(false);
new Thread() {
public void run() {
WebserviceMethod wb = new WebserviceMethod();
if (wb.DeleteEmployee(
VerificationUtils
.GetInstance()
.CreateToken(),
personId) == 1) {
Message msg = new Message();
msg.obj = SwitchActivityValue.SWITCH_DELETEPERSON_OK;
mHandler.sendMessage(msg);
}
}.start();
}
@Override
public void handleMessage(Message msg){
super.handleMessage(msg);
SwitchActivityValue value = (SwitchActivityValue)msg.obj;
switch (value) {
case SWITCH_DELETEPERSON_OK:
ManageUtils.EmployeeListDataForAdmin.personInfos.clear();
ManageUtils.EmployeeListDataForAdmin.currentPage = 0;
mActivity.switchActivity(mValue);
break;
case SWITCH_DELETEPERSON_FAILED:
break;
default:
break;
}
mActivity.showMessage(value);
}
Such as the example,you can bind the data in the Handler.When the thread finished,it use hanlder to sendmessage to notice handleMessage handle others.
Upvotes: 1
Reputation: 12134
Hope this may work for you, here i used Asynchronous Task instead of thread
public class MainActivity extends Activity {
String s;
List<String> headersList = new ArrayList<String>();
List<String> contentList = new ArrayList<String>();
ListView listview;
StableArrayAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listview = (ListView) findViewById(R.id.listView1);
// threadStart();
// Here i implemented Asynchronous Task instead of Thread
new SampleAsyncTask().execute();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public class SampleAsyncTask extends AsyncTask<Void, Void, Void> {
private final ProgressDialog dialog = new ProgressDialog(
MainActivity.this);
protected void onPreExecute() {
this.dialog.setMessage("Loading...");
this.dialog.setCancelable(false);
this.dialog.show();
}
@Override
protected Void doInBackground(Void... params) {
try {
webRequest();
adapter = new StableArrayAdapter(MainActivity.this,
android.R.layout.simple_list_item_1, headersList);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void result) {
// Here if you wish to do future process for ex. move to another
// activity do here
listview.setAdapter(adapter);
if (dialog.isShowing()) {
dialog.dismiss();
}
}
}
private class StableArrayAdapter extends ArrayAdapter<String> {
HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();
public StableArrayAdapter(Context context, int textViewResourceId,
List<String> objects) {
super(context, textViewResourceId, objects);
// TODO Auto-generated constructor stub
for (int i = 0; i < objects.size(); ++i) {
mIdMap.put(objects.get(i), i);
}
}
@Override
public long getItemId(int position) {
String item = getItem(position);
return mIdMap.get(item);
}
@Override
public boolean hasStableIds() {
return true;
}
}
public void webRequest() throws Exception {
String servisURL = "http://www.sczg.unizg.hr/student-servis/";
Document doc = Jsoup.connect(servisURL).get();
Elements jobNode = doc.select("div.jobBox");
Elements headersNode = jobNode.select("h1");
Elements contentNode = jobNode.select("content");
for (int i = 0; i < headersNode.size(); i++) {
headersList.add(headersNode.get(i).text());
}
for (int i = 0; i < contentNode.size(); i++) {
contentList.add(contentNode.get(i).text());
}
}
}
Upvotes: 2
Reputation: 5429
At first I propose you to read this guide, especially about Using AsyncTask instead raw Thread.
At second, as I understand, you want to invoke adapterInit from UI thread? So, you can try this:
runOnUiThread( // <-- method from Activity
new Runnable()
{
@Override
public void run() {
// TODO Auto-generated method stub
adapterInit();
}
}
);
Upvotes: 2
Reputation: 941
Maybe the problem is that you are not calling the method notifyDataSetChanged() on the adapter to force it to update his informations, it's like notifying the adapter that the underlaying data were updated and that it needs to refresh the associated listview.
You should call it after you fetch the data from the website.
Upvotes: 1