imot01
imot01

Reputation: 97

List view doesn't show text

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

Answers (4)

Dev2007
Dev2007

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

Aerrow
Aerrow

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

Oleksii K.
Oleksii K.

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

Vittorio Cozzolino
Vittorio Cozzolino

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

Related Questions