Android:我的列表视图在向数据添加新行后,无法在触摸模式下选择行

问题描述:

我有一个活动和一个线程。线程处理数据(之后数据将从Internet活动中抓取,现在,它每10秒自动添加一行)。问题是,在添加新行后,我无法再触摸物品,重新获得焦点,我必须按下硬件键盘上的向上或向下箭头或菜单按钮。 当然,我首先想到重新设置.setFocusableOnTouchMode为true,但这似乎并没有解决我的问题。或者至少,我没有把它放在正确的地方。反正这是我的代码:Android:我的列表视图在向数据添加新行后,无法在触摸模式下选择行

的活动:

$ 
    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; 

       } 
      } 
     } 

现在确定的主题。

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(); 

     } 
     } 
     } 
     } 

好了,感谢上前进,任何解决方案将appretiated

+0

两件事......我想你应该只在UI线程中运行'notifyDataSetChanged',但我可能是错的。其次,我相信'notifyDataSetChanged'只适用于使用适配器的'add','insert','remove'和'clear方法。看起来你正在重新分配底层数组,这可能是问题所在。看[这个问题](http://*.com/questions/3669325/notifydatasetchanged-example)。 – Craigy

+0

Ahm ..我是否应该添加,删除或删除您正在讨论的功能?我的适配器不提供这些,我应该使用不同类型的适配器吗? – user982962

+0

欢迎来到计算器!如果您发现特定回复有帮助,请投票。如果某个特定回复是正确的,请点击回复旁边的复选标记以接受该回复。 –

你不能直接从一个线程不是UI线程修改UI元素。如果要从其他线程修改UI元素,则必须调用函数runOnUiThread。这意味着你将有一个refernce的活动传递给刷新类在它的构造函数,因此你可以做你的线程以下调用:

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

这就是说,如果我是你,我会放弃这个而只需使用AsyncTaskLoader。它更容易,而且该类专门用于异步加载像listview之类的元素。你现在编写代码的方式不会很好,并且容易出现各种错误。在android中,一般的经验法则是不使用原始的Thread类,除非你必须这样做。使用AsyncTaskLoader,AsyncTask或IntentService。

最后注意,如果您开发的API级别低于10,您仍然可以通过android Support Package访问AsyncTaskLoader类。

+0

在30分钟左右,我就可以测试这个解决方案。感谢您提前回答! – user982962

+0

我现在正在尝试你所说的话。我只是说,我放的代码示例工作,它只是有我说的问题。但你可能是对的。我只学习了常规的Java,我试图将其应用于Android,但只是尝试了解那里的指南和示例。这就是为什么在很多情况下,我可能会有一些解决方案效率不高。 – user982962

+0

很难相信这听起来可能。这并没有解决问题。事实上,我发现只调用.notifyDataSetChanged()而不进行任何更改是有问题的。 – user982962