9

私は私を夢中にさせる奇妙な問題を抱えています。私のAndroidアプリケーションでは、ArrayAdapterから拡張する独自のアダプターをカスタマイズしました。アダプターを追加したListViewのアイテムには、テキスト(編集不可)、編集可能テキスト、またはスピナーのいずれかのラベルを付けることができます。クレイジーなのは、ListViewをスクロールすると、2つの問題が発生することです。

(1)スクロールしただけなのに、スピナー項目に表示される(選択した)値が変わることがあります!! スピナーをクリックすると、古い選択値が引き続き表示されます(スピナーによって表示されるはずの値)(2)スクロールすると、ListViewItemsの順序が変わります。

=>しかし、アダプタ内のデータは変更されません(データ自体も順序も変更されません)-したがって、ビュー自体の問題である必要がありますか?!おそらくAndroidはバックグラウンドでキャッシュし、ListViewItemsをすぐに更新しないか、そのように更新しませんか?!

誰か助けてくれませんか?

ありがとう!

わかりました、私はあまり良くない解決策を見つけました、しかしそれは働きます。メモリとパフォーマンスに関しては最適ではありませんが、convertViewを使用しなくなりました。私の場合、ListViewのアイテムの最大数は15なので、問題ないはずです。これが私のAdapter-Classです。

 public class FinAdapter extends ArrayAdapter<Param>{
    public Param[] params;
    private boolean merkzettel;
    protected EditText pv;

    public FinAdapter(Context context, int textViewResourceId, Param[] items, boolean merkzettel) {
        super(context, textViewResourceId, items);
        this.params = items;
        this.merkzettel = merkzettel;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final Param p = params[position];
        if(p != null){
            if(merkzettel){
                if (convertView == null) {
                    LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    convertView = vi.inflate(R.layout.merk_det_item, null);
                }
                TextView tvl = (TextView) convertView.findViewById(R.id.paramM);
                TextView edl = (TextView) convertView.findViewById(R.id.param_valueM);
                TextView pal = (TextView) convertView.findViewById(R.id.param_unitM);
                if (tvl != null) {
                    tvl.setText(p.getName());                            
                }
                if(pal != null){
                    pal.setText(p.getUnit());
                }
                if(edl != null){
                    edl.setText(p.getDefData());
                }
            }
            else{
                if(p.isSelect()){

                if (convertView == null) {
                    LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    convertView = vi.inflate(R.layout.fin_prod_list_item_select, null);
                }            
                TextView tvs = (TextView) convertView.findViewById(R.id.paramS);
                Spinner sp = (Spinner) convertView.findViewById(R.id.spinner_kalk);
                TextView paU = (TextView) convertView.findViewById(R.id.param_unitS);


                if (tvs != null) {
                    tvs.setText(p.getName());                            
                }
                if(paU != null){
                    paU.setText(p.getUnit());
                }
                if(sp != null){
                    String[] values = new String[p.getData().size()];
                    for(int i=0; i<values.length; i++){
                        values[i] = p.getData().get(i);
                    }
                    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this.getContext(), android.R.layout.simple_spinner_item, values);
                    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                    sp.setAdapter(adapter);
                    sp.setSelection(p.getData().indexOf(p.getDefData()));
                    sp.setOnItemSelectedListener(new OnItemSelectedListener(){
                        public void onItemSelected(AdapterView<?> parent,
                                View convertView, int pos, long id) {
                            p.setDefData(p.getData().get(pos));
                            p.setChanged(true);
                        }
                        public void onNothingSelected(AdapterView<?> arg0) {
                            // TODO Auto-generated method stub

                        }

                    });
                }
            }       
            else if(p.isEdit()){
                if (convertView == null) {
                    LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    convertView = vi.inflate(R.layout.fin_prod_list_item_edit, null);
                }
                TextView pa = (TextView) convertView.findViewById(R.id.param);
                pv = (EditText) convertView.findViewById(R.id.param_value);
                TextView paE = (TextView) convertView.findViewById(R.id.param_unit);
                if (pa != null) {
                    pa.setText(p.getName());                            
                }
                if(paE != null){
                    paE.setText(p.getUnit());
                }
                if(pv != null){
                    pv.setText(p.getDefData());
                    pv.setOnEditorActionListener(new OnEditorActionListener(){
                        public boolean onEditorAction(TextView convertView, int actionId,
                                KeyEvent event) {
                            // TODO Auto-generated method stub
                            p.setDefData(pv.getText().toString());
                            p.setChanged(true);
                            return false;
                        }                   
                    }); 
                }

            }
            else if(p.isLabel()){
                if (convertView == null) {
                    LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    convertView = vi.inflate(R.layout.fin_prod_list_item_label, null);
                }
                TextView tvl = (TextView) convertView.findViewById(R.id.paramL);
                TextView edl = (TextView) convertView.findViewById(R.id.param_valueL);
                TextView pal = (TextView) convertView.findViewById(R.id.param_unitL);
                if (tvl != null) {
                    tvl.setText(p.getName());                            
                }
                if(pal != null){
                    pal.setText(p.getUnit());
                }
                if(edl != null){
                    edl.setText(p.getDefData());
                }   
            }}
        }
        return convertView;
    }
}
4

3 に答える 3

5

リスト内の複数のアイテムタイプで同様の問題が発生しました。私の場合、リストアイテムはセクション(ラベル)アイテムまたは共通リストアイテムのいずれかでした。

getViewTypeCountこのようなタイプのリストを操作するには、メソッドをオーバーライドする必要がありgetItemViewTypeます。このようなもの:

private static final int ITEM_VIEW_TYPE_ITEM = 0;
private static final int ITEM_VIEW_TYPE_SEPARATOR = 1;

@Override
public int getViewTypeCount() {
    return 2;
}

@Override
public int getItemViewType(int position) {
    return this.getItem(position).isSection() ? ITEM_VIEW_TYPE_SEPARATOR : ITEM_VIEW_TYPE_ITEM;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final Item item = this.getItem(position);

    if (convertView == null) {
        convertView = mInflater.inflate(item.isSection() ? R.view1 : R.view2, null);
    }

    if(item.isSection()){
        //...
    }
    else{
        //...
    }

    return convertView;
}

そうすれば、convertViewパラメーターは常に正しく、必要なタイプが含まれます。

そしてもう1つpublic Param[] params、基本クラスにすでにフィールドがある場合は、フィールドを明示的に追加しましたArrayAdapter<Param>

BaseAdapterクラスから継承することをお勧めします。

編集:Spinnerこれがあなたの仕事 をするためにあなたが使うことを試みることができるコードです:

sp.setTag(p);
sp.setOnItemSelectedListener(new OnItemSelectedListener(){
public void onItemSelected(AdapterView<?> parent, View convertView, int pos, long id) {
    Param currentItem = (Param)parent.getTag();
    currentItem.setDefData(currentItem.getData().get(pos));
    currentItem.setChanged(true);
}
//...

getTagsetTagメソッドの組み合わせを使用してみてください。イベントハンドラーとfinal変数で同様の問題が発生したことを覚えていますが、それらの原因を完全に忘れてしまったため、これが発生する理由を正確に説明することはできません。

于 2012-08-16T08:33:58.523 に答える
1

サムが述べたように、Androidシステムは、リソースを節約するために、可能であれば常にリサイクルを試みます。つまり、開発者は自分自身を追跡する必要がありViewますListView。エンティティ、またはいわゆるプレゼンテーションデータ構造の場合、次のように、選択/選択解除された状態を追跡するための何かを持つことができます。

class PresentationData {
    // other stuffs..
    boolean isSelected = false;
}

これらのデータ構造をにマッピングし、Adapterアイテムがクリックされた場合は、状態をtrueに設定します。listPresentationData.get(selected_position).isSelected = true

さてgetView()、アダプタので、データのプレゼンテーションを正しく追跡してください。

if(listPresentationData.get(position).isSelected) 
{ 
    // set background color of the row layout..or something else 
}

また、言及する価値があるのは、すべてのビューにメモリキャッシュを用意することです。これは通常、ViewHolderパフォーマンスを向上させるためにも呼び出されます。

于 2012-08-15T16:06:07.967 に答える
0

誰もが言うように、Androidはビューをリサイクルします。どういう意味ですか?リストに10個のアイテムがあり、そのうち3個だけが画面に表示されているとします。下にスクロールすると、最初の文字が消え、4番目の文字が表示されます。4番目のアイテムはすでにAndroidシステムにありましたが、5番目のアイテムは同じビューを使用して最初のアイテムから作成されました。私の場合、デフォルトの背景を持つTextViewがありました。しかし、何らかの条件が満たされた場合は、背景を変更します。

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ...
    if (someCondition) {
        holder.textView.setBackground(R.drawable.different_background)
    }
    ...
}

問題は、条件が満たされない場合にデフォルトの背景を戻さないことでした(ビューはアイテムごとに作成されたと思っていたため)。この問題は、最初のアイテムの条件がtrueの場合に発生したため、リサイクルされたビューがデフォルトの背景ではなく、different_backgroundで使用されました。この問題を回避するには、常に条件の両方のブランチを設定し、次のようにデフォルト値を設定する必要がありました。

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ...
    if (someCondition) {
        holder.textView.setBackground(R.drawable.different_background)
    } else {
        holder.textView.setBackground(R.drawable.default_background)
    }
    ...
}
于 2020-02-08T16:05:57.823 に答える