【问题标题】:Android: AsyncTask UI update issueAndroid:AsyncTask UI 更新问题
【发布时间】:2012-07-07 07:35:16
【问题描述】:

在下面的代码中,我试图创建一个ListActivity。 此列表的元素由自定义 ArrayAdapter - OrderAdapter 填充。

所有的元素获取机制都在 AsyncTask 类中。 我可以在m_adapter 中设置元素,但无法更新 List 的 UI。

活动正在强制关闭。

代码:

public class SoftwarePassionView extends ListActivity {

    private ProgressDialog m_progressDialog = null;
    private ArrayList<Order> m_orders = null;
    private OrderAdapter m_adapter; // Defined Below
    private Runnable viewOrders;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        try {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.softwarepassionview);
            m_adapter = new OrderAdapter(SoftwarePassionView.this,
                    R.layout.row, m_orders);

            new AsyncOperation().execute();

        } catch (Exception e) {
            Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show();
        }
    }

    public class OrderAdapter extends ArrayAdapter<Order> {

        private ArrayList<Order> items;

        public OrderAdapter(Context context, int textViewResourceId,
                ArrayList<Order> elements) {
            super(context, textViewResourceId, elements);
            this.items = elements;
        }

        public void setList(ArrayList<Order> items) {
            this.items = new ArrayList<Order>();
            this.items.addAll(items);

        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            super.getView(position, convertView, parent);
            View v = convertView;
            try {
                if (v == null) {
                    LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    v = vi.inflate(R.layout.row, null);
                }
                Order o = items.get(position);
                if (o != null) {
                    TextView orderName = (TextView) v
                            .findViewById(R.id.topText);
                    TextView orderStatus = (TextView) v
                            .findViewById(R.id.bottomText);
                    orderName.setText(o.getOrderName());
                    orderStatus.setText(o.getOrderStatus());
                }
            } catch (Exception e) {
                Toast.makeText(SoftwarePassionView.this, e.toString(),
                        Toast.LENGTH_SHORT).show();
            }
            return v;
        }
    }

    public class AsyncOperation extends AsyncTask {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected Object doInBackground(Object... params) {
            getOrders();
            if (m_orders != null && m_orders.size() > 0) {
                m_adapter.setList(m_orders);
            }
            return null;
        }

        @Override
        protected void onPostExecute(Object result) {
            super.onPostExecute(result);
            m_adapter.notifyDataSetChanged();
            setListAdapter(m_adapter);
        }
    }

    private void getOrders() {
        try {
            m_orders = new ArrayList<Order>();
            Order o1 = new Order();
            o1.setOrderName("T-Shirt Purchase");
            o1.setOrderStatus("Dispatched");
            Order o2 = new Order();
            o2.setOrderName("Deo Purchase");
            o2.setOrderStatus("Pending");
            m_orders.add(o1);
            m_orders.add(o2);

            Thread.sleep(2000);
        } catch (Exception e) {
            Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show();
        }
    }

}

【问题讨论】:

  • 删除 super.onPostExecute() 并尝试,否则再次定义 adater 并将其设置在列表视图中。
  • 都试过了。对于第二点,我在onPostExecute 中创建了一个新的适配器OrderAdapter adapter = new OrderAdapter(SoftwarePassionView.this, R.layout.row2, m_orders); setListAdapter(adapter);。不工作

标签: java android android-asynctask


【解决方案1】:

我有修复错误现在试试

public class SoftwarePassionView extends ListActivity {

private ProgressDialog m_progressDialog = null;
private ArrayList<Order> m_orders = new ArrayList<Order>(); //why you have putting it null?
private OrderAdapter m_adapter; // Defined Below
private Runnable viewOrders;

@Override
protected void onCreate(Bundle savedInstanceState) {
    try {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.softwarepassionview);
        m_adapter = new OrderAdapter(SoftwarePassionView.this,
                R.layout.row, m_orders);
        setListAdapter(m_adapter); // you are getting npe as you have not init "m_orders"
        new AsyncOperation().execute();

    } catch (Exception e) {
        Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show();
    }
}

public class OrderAdapter extends BaseAdapter {

    private ArrayList<Order> items=new ArrayList<Order>();

    public OrderAdapter(Context context, int textViewResourceId,
            ArrayList<Order> elements) {
        //super(context, textViewResourceId, elements);
        this.items = elements;
    }

    public void setList(ArrayList<Order> items) {
        this.items.clear(); 
        this.items.addAll(items);
        this.notifyDataSetChanged();

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        super.getView(position, convertView, parent);
        View v = convertView;
        try {
            if (v == null) {
                LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = vi.inflate(R.layout.row, null);
            }
            Order o = items.get(position);
            if (o != null) {
                TextView orderName = (TextView) v
                        .findViewById(R.id.topText);
                TextView orderStatus = (TextView) v
                        .findViewById(R.id.bottomText);
                orderName.setText(o.getOrderName());
                orderStatus.setText(o.getOrderStatus());
            }
        } catch (Exception e) {
            Toast.makeText(SoftwarePassionView.this, e.toString(),
                    Toast.LENGTH_SHORT).show();
        }
        return v;
    }

public int getCount() {

    return this.items.size();
}

public Object getItem(int arg0) {
    // TODO Auto-generated method stub
    return this.items.get(arg0);
}

public long getItemId(int arg0) {
    // TODO Auto-generated method stub
    return 0;
}

}

public class AsyncOperation extends AsyncTask {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected Object doInBackground(Object... params) {
        getOrders();
       // if (m_orders != null && m_orders.size() > 0) {  NO nead to set list here
       //     m_adapter.setList(m_orders);
       // }
        return null;
    }

    @Override
    protected void onPostExecute(Object result) {

        if (m_orders != null && m_orders.size() > 0) {  
            m_adapter.setList(m_orders);
        }
         super.onPostExecute(result);
        //setListAdapter(m_adapter);
    }
}

private void getOrders() {
    try {
        m_orders = new ArrayList<Order>();
        Order o1 = new Order();
        o1.setOrderName("T-Shirt Purchase");
        o1.setOrderStatus("Dispatched");
        Order o2 = new Order();
        o2.setOrderName("Deo Purchase");
        o2.setOrderStatus("Pending");
        m_orders.add(o1);
        m_orders.add(o2);

        Thread.sleep(2000);
    } catch (Exception e) {
        Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show();
    }
}

}

【讨论】:

  • 唷...感谢更正版本。不工作。甚至尝试了一个新的简化项目。此错误出现在日志E/ArrayAdapter(7245): You must supply a resource ID for a TextView 中。我将m_adapter = new OrderAdapter(SoftwarePassionView.this, R.layout.row, m_orders); 更改为m_adapter = new OrderAdapter(SoftwarePassionView.this, R.layout.row, R.id.tvOrderName, m_orders);(我的row.xml 中TextView 的ID),但现在它给了我NPE。有什么建议。 &感谢您提供这么多帮助
  • 它起作用了..你能解释一下BaseAdapter 有什么不同吗?谢谢
  • 说真的,我也不知道原因..:) 我总是使用BaseAdapter,因为 Base 适配器是 Adapter 的 Base 类。
【解决方案2】:

检查this post,问题几乎相同。

我认为由于项目具有相同的引用(从活动传递到适配器),所以项目(在适配器和活动上都指向相同的 ArrayLists)所以两者都是明确的,所以这些行没有意义,因为两者都是空的

试试这样的:

public class OrderAdapter extends ArrayAdapter<Order> {
        // private ArrayList<Order> items;
        private ArrayList<Order> items = new ArrayList<Order>();

        public OrderAdapter(Context context, int textViewResourceId,
                ArrayList<Order> elements) {
            super(context, textViewResourceId, elements);
            this.items = elements;
        }

        public void setList(ArrayList<Order> items) {
        this.items.addAll(items);

        }

和:

@Override
        protected void onPostExecute(Object result) {
            super.onPostExecute(result);
            //m_adapter.notifyDataSetChanged();
            // setListAdapter(m_adapter);
            m_adapter.notifyDataSetChanged();
        }

并在创建m_adapter 后使用setListAdapter(m_adapter);

【讨论】:

  • 如果您的意思是在onCreate() 中创建m_adapter 之后设置setListAdapter(m_adapter);,那么它就是给nullPointerException
  • nullPointerException 的原因是,在调用setListAdapter 时,m_orders 为空。我已经解决了问题并在下面发布答案..看看..
猜你喜欢
  • 1970-01-01
  • 2016-01-23
  • 1970-01-01
  • 1970-01-01
  • 2014-03-26
  • 1970-01-01
  • 2021-01-20
  • 2011-05-28
  • 1970-01-01
相关资源
最近更新 更多