0

I have an Activity and a Thread. The thread handles the data (later that data will be grabbed from Internet activity, for now, it just automatically adds a new row each 10 seconds). The thing is, after a new row being add, I can't touch the items anymore, to regain focus, I must press the up or down arrow on my hardware keyboard, or the menu button. Of course I first thought to re-set the .setFocusableOnTouchMode to true, but this didn't seem to solve my problem. Or at least, I'm not setting it on the right place. Anyway this is my code:

The Activity:

    $
    package com.ejemplolisbox;



import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class EL extends Activity {
    /**
     * @see android.app.Activity#onCreate(Bundle)
     */





    public Refresh actualizar;
        // The thread
    public static ListView g;
    public static EfficientAdapter instance ;
        // The adapter (is a custom made adapter, I didn't do it myself, just grabbed it from the Internet)

        public static String[] abbreviations = {  "Item0",
                "Item1", "Item2"};







            /** Called when the activity is first created. */

            public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);
                g = (ListView) findViewById(R.id.lv_country);
                g.setFocusable(true);
                g.setFocusableInTouchMode(true);
                instance = new EfficientAdapter(this);
                                // The adapter is now set to this instance
                g.setAdapter(instance);
                actualizar = new Refresh();
                actualizar.start();
                                //I start the thread

                g.setOnFocusChangeListener(new OnFocusChangeListener() {

                    public void onFocusChange(View arg0, boolean arg1) {
                        // TODO Auto-generated method stub
                        // Code should be here (??)
                    }

                });
                g.setOnItemClickListener(new AdapterView.OnItemClickListener() {

                    public void onItemClick(AdapterView a, View v, int position,
                long id) {

                //use position to get clicked position
                //your code goes here

                }
                });
            }
            public static class EfficientAdapter extends BaseAdapter {
                private LayoutInflater mInflater;

                public EfficientAdapter(Context context) {
                    mInflater = LayoutInflater.from(context);


                }

                public int getCount() {
                    return abbreviations.length;
                }

                public Object getItem(int position) {
                    return position;
                }

                public long getItemId(int position) {
                    return position;
                }

                public View getView(int position, View convertView, ViewGroup parent) {

                    ViewHolder holder;
                    if (convertView == null) {
                        convertView = mInflater.inflate(R.layout.rowlayout, null);
                        holder = new ViewHolder();
                        holder.text1 = (TextView) convertView
                                .findViewById(R.id.TextView01);


                        convertView.setTag(holder);
                    } else {
                        holder = (ViewHolder) convertView.getTag();
                    }

                    holder.text1.setText(abbreviations[position]);



                    return convertView;

                }

                static class ViewHolder {
                    TextView text1;

                }
            }
        }

OK now the Thread.

 package com.ejemplolisbox;
     public class Refresh extends Thread{
     public void run(){
    while(true){
    String[] ex=EL.abbreviations;
    String[] ne=new String[ex.length+1];
    for(int i=0;i<ex.length;i++){
        ne[i]=ex[i];
    }
    ne[ex.length]="newItem"+ex.length;
    EL.abbreviations=ne;
    try{
    EL.instance.notifyDataSetChanged();
    EL.g.setFocusableInTouchMode(true);


    }
    catch(Exception e){
        int i = 0;
        EL.g.setFocusableInTouchMode(true);
    }
    EL.g.setFocusableInTouchMode(true);
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();

        }
        }
        }
        }

Well, thanks on advance, any solution will be appretiated

user982962
  • 21
  • 1
  • 6
  • Two things... I think you are supposed to run `notifyDataSetChanged` only in the UI thread, but I could be wrong. Second, I believe `notifyDataSetChanged` only works when you use the adapter's `add`, `insert`, `remove` and `clear methods. It appears that you are reassigning the underlying array, which could be the problem. See [this question](http://stackoverflow.com/questions/3669325/notifydatasetchanged-example). – skynet Oct 24 '11 at 20:17
  • Ahm.. Should I have and add, inster or remove functions you are talking about? My adapter does not provide those, should I use a different type of adapter? – user982962 Oct 24 '11 at 20:22
  • Welcome to stackoverflow! If you find a particular response helpful please up vote it. If a particular response is right, please accept it by clicking the checkmark next to the response. – Kurtis Nusbaum Oct 24 '11 at 20:30

1 Answers1

0

You can't directly modify UI elements from a thread that isn't the UI thread. If you want to modify a UI element from a different thread, you have to call the function runOnUiThread. That means you'll have to pass a refernce to the activity to the Refresh class in it's constructor so you can do the following call on your thread:

activity.runOnUiThread(new Runnable(){
  public void run(){
    EL.g.setFocusableInTouchMode(true);
  }
});

That said, if I were you I'd scrap this and just use an AsyncTaskLoader instead. It's much easier and the class was specifically created for asynchronously loading up elements in things like a listview. The way you have the code written right now is not going to work very well and is prone to all kinds of error. In android, a general rule of thumb is to not use the raw Thread class unless you abosultely have to. Use either the AsyncTaskLoader, AsyncTask, or IntentService.

Final note, if you're developing for API levels less than 10, you can still access the AsyncTaskLoader class via the android Support Package.

Kurtis Nusbaum
  • 30,445
  • 13
  • 78
  • 102
  • Ok in 30 minutes or so I'll be able to test this solution. Thank you for answering in advance! – user982962 Oct 24 '11 at 20:35
  • I'm now goint to try what you've said. I'm just saying, the code example I put worked, it just had the problem I said. But you're probably right. I only learned regular Java and I'm trying to apply this to Android, but just by trying to understand the guides and examples out there. That's why in many cases I may have solutions that are not quite efficent. – user982962 Oct 24 '11 at 20:45
  • Well as hard to believe this might sound. This didn't solve the problem. In fact, I discovered that just calling the .notifyDataSetChanged() without making any changes at all is problematic. – user982962 Oct 26 '11 at 23:20
  • NO, I WAS WRONG, IT WORKED, Thank you so much! – user982962 Oct 26 '11 at 23:44