PageView 内的 Listview - NotifyDatasetChanged 未调用

Posted

技术标签:

【中文标题】PageView 内的 Listview - NotifyDatasetChanged 未调用【英文标题】:Listviews inside PageViewer - NotifyDatasetChanged not called 【发布时间】:2014-10-19 23:32:37 【问题描述】:

我的列表视图快疯了。

我在 ViewPager 中有几个列表视图(每一个都不同)。

在每一行,我都有一个拍照按钮。我的列表视图中的所有数据都存储在 ArrayList 中,也存储在 Sqlite 中。在 onActivityResult,我在 db 中设置我的值,修改我用于适配器的 ArrayList,并调用 notifyDataSetChanged,以便我可以更改按钮图标(显示已拍摄的图片)。

我非常接近做到这一点。当我在 viewpager 中更改页面时,位图不会改变(因为未调用 getView),但是当我滚动列表视图以使行消失然后返回时,位图正在改变(因为我使用持有人模式,所以 getView 被调用。

我的适配器将变量 Metrica 作为参数:

public class Metrica 
private int id;
private int clienteId;
private String description;
private int tipo;
private int proyectoProductoId;
private ArrayList<Formulario> lForms; // <-- this is the arraylist which populate the LV
[getters and setters...] 

Formulario 对象:

public class Formulario 
private int id;
private int capturaId;
private Producto producto;
private String cantidad; // qty
private String imagen; // pic
private boolean picTaken = false;
private int sync;

我的问题只是在我拍照的时候,即在onActivityResult中。

这是活动代码:

public class MetricaTabs extends ActionBarActivity implements
        ActionBar.TabListener 
    static ArrayList<Metrica> lMetricas;
    private SharedPreferences prefs;
    public static Context ctx;
    private int metricaId;
    ActionBar actionBar;
    static ListView lstForm;
    Metrica metrica;
    static EditText transparentEt;
    FormsAdapter adbForm;
    public static Uri imageFileUri;
    SectionsPagerAdapter mSectionsPagerAdapter;
    ViewPager mViewPager;
    private static int idCaptura;
    private int mAction;
    int numTab;
    private final int TAKE_PIC_FORM = 1000;
    ProgressDialog pd; 

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_metrica_tabs);
        ctx = this;

        FormHandler fh = new FormHandler(ctx);
        MetricaHandler mh = new MetricaHandler(ctx);

        // I should optimize this with a join
        lMetricas = mh.getAllMetricas();
        int i = 0;
        for (Metrica m : lMetricas) 
            ArrayList<Formulario> lForms = fh.getAllForms(m.getId(), idCaptura);
            lMetricas.get(i).setlForms(lForms);
            i++;
        

        fh.close();
        mh.close();


        // Create the adapter that will return a fragment for each of the three
        // primary sections of the activity.
        mSectionsPagerAdapter = new SectionsPagerAdapter(
                getSupportFragmentManager());

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        // When swiping between different sections, select the corresponding
        // tab. We can also use ActionBar.Tab#select() to do this if we have
        // a reference to the Tab.
        mViewPager
                .setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() 
                    @Override
                    public void onPageSelected(int position) 
                        actionBar.setSelectedNavigationItem(position);

                    
                );

        mSectionsPagerAdapter.notifyDataSetChanged();
        // For each of the sections in the app, add a tab to the action
        // bar.
        for (int j = 0; j < mSectionsPagerAdapter.getCount(); j++) 
            actionBar.addTab(actionBar.newTab()
                    .setText(mSectionsPagerAdapter.getPageTitle(j))
                    .setTabListener(MetricaTabs.this));
        

    

    private void initDatos() 
        prefs = PreferenceManager.getDefaultSharedPreferences(this);
        String activityName = getClass().getSimpleName().toString();
        prefs.edit().putString("FrontActivity", activityName).commit();
        idCaptura = prefs.getInt("capturaId", 0);

    

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
        switch (requestCode) 
        case TAKE_PIC_FORM:
            if (resultCode == RESULT_OK) 

                mAction = TAKE_PIC_FORM;
                int position = prefs.getInt("positionInList", 0);
                metricaId = prefs.getInt("metricaId", 0);
                String marca = prefs.getString("marca", null);
                int proyectoproducto = prefs.getInt("proyectoproducto", 0);
                String producto = prefs.getString("producto", null);
                prefs.edit().remove("positionInList").commit();
                prefs.edit().remove("metricaId").commit();
                prefs.edit().remove("marca").commit();
                prefs.edit().remove("producto").commit();

                FormHandler fh = new FormHandler(ctx);
                String picName = RutaActivity.getPicName(mAction, idCaptura,
                        metricaId, proyectoproducto);
                Bundle extras = data.getExtras();
                Bitmap bmp = (Bitmap) extras.get("data");
                savePicture(mAction, bmp);

                // Insert or update in sqlite

                Formulario form = new Formulario();
                form.setImagen(picName);
                form.setCapturaId(idCaptura);

                Producto p = new Producto();
                p.setId(proyectoproducto);
                p.setMarca(marca);
                p.setMetricaId(metricaId);
                p.setProducto(producto);

                form.setProducto(p);

                form.setSync(0);
                boolean existForm = fh.existForm(form);
                if (!existForm)
                    fh.addForm(form);
                else
                    fh.updateForm(form);



                metrica = lMetricas.get(numTab);
                metrica.getlForms().set(position, form);
                lMetricas.set(numTab, metrica);
                // If I don't put this line, we work in the Adapter of the second Tab
                adbForm = new FormsAdapter(this, 0, metrica, idCaptura);
                adbForm.setMetrica(metrica);
                adbForm.notifyDatasetChanged(); // <-- ### This doesn't do anything ###
                fh.close();
            
            break;

        
    


    @Override
    public void onTabSelected(ActionBar.Tab tab,
            FragmentTransaction fragmentTransaction) 
        // When the given tab is selected, switch to the corresponding page in
        // the ViewPager.
        mViewPager.setCurrentItem(tab.getPosition());
        SharedPreferences prefs = PreferenceManager
                .getDefaultSharedPreferences(ctx);
        numTab = tab.getPosition();
        prefs.edit().putInt("numTab", numTab).commit();

    

    @Override
    public void onTabUnselected(ActionBar.Tab tab,
            FragmentTransaction fragmentTransaction) 
    

    @Override
    public void onTabReselected(ActionBar.Tab tab,
            FragmentTransaction fragmentTransaction) 
    

    /**
     * Here we store the file url as it will be null after returning from camera
     * app
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) 
        super.onSaveInstanceState(outState);
        // save file url in bundle as it will be null on scren orientation
        // changes
        outState.putParcelable("file_uri", imageFileUri);
    

    /*
     * Here we restore the fileUri again
     */
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) 
        super.onRestoreInstanceState(savedInstanceState);

        // get the file url
        imageFileUri = savedInstanceState.getParcelable("file_uri");

    

    /**
     * A @link FragmentPagerAdapter that returns a fragment corresponding to
     * one of the sections/tabs/pages.
     */
    public class SectionsPagerAdapter extends FragmentPagerAdapter 

        public SectionsPagerAdapter(android.support.v4.app.FragmentManager fm) 
            super(fm);
        

        @Override
        public android.support.v4.app.Fragment getItem(int position) 

            return PlaceholderFragment.newInstance(position);
        

        @Override
        public int getItemPosition(Object object) 
            return POSITION_NONE;
        

        @Override
        public int getCount() 
            if (lMetricas != null) 
                return lMetricas.size();
            
            return 0;

        

        @Override
        public CharSequence getPageTitle(int position) 
            Locale l = Locale.getDefault();
            return lMetricas.get(position).getDescription().toUpperCase(l);
        
    

    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends
            android.support.v4.app.Fragment 
        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        private static final String POSITION = "pos";

        /**
         * Returns a new instance of this fragment for the given section number.
         */
        public static PlaceholderFragment newInstance(int numTab) 

            PlaceholderFragment fragment = new PlaceholderFragment();
            Bundle args = new Bundle();

            args.putInt(POSITION, numTab);
            fragment.setArguments(args);
            return fragment;
        

        public PlaceholderFragment() 

        

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) 
            View rootView = inflater.inflate(R.layout.fragment_metrica_tabs,
                    container, false);
            lstForm = (ListView) rootView.findViewById(R.id.list_form);
            transparentEt = (EditText) rootView
                    .findViewById(R.id.transparentEt);
            int numTab = getArguments().getInt(POSITION);
            // Get the data
            Metrica metrica = new Metrica();
            if (lMetricas != null && lMetricas.size() > 0) 
                metrica = lMetricas.get(numTab);
            

            FormsAdapter adbForm = new FormsAdapter(getActivity(), 0, metrica, idCaptura);
            lstForm.setAdapter(adbForm);

            adbForm.notifyDataSetChanged();
            return rootView;
        
    

这是我使用支架模式的自定义适配器的完整代码:

公共类 FormsAdapter 扩展 ArrayAdapter 私有 ArrayList lForm; 私有上下文 ctx; 私有 int metricaId,capturaId; 私有公制公制; 公共静态 int TAKE_PIC_REQUEST = 1000; 私有 SharedPreferences 首选项;

public int getMetricaId() 
    return metricaId;


public void setMetricaId(int metricaId) 
    this.metricaId = metricaId;


public FormsAdapter(Context context, int textViewResourceId, Metrica met,
        int cId) 
    super(context, textViewResourceId, met.getlForms());

    setMetrica(met);
    lForm = met.getlForms();
    ctx = context;
    prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
    metricaId = getMetrica().getId();
    capturaId = cId;
    this.setlForm(lForm);


public int getViewTypeCount() 
    return getCount();


public int getItemViewType(int position) 
    return position;


public int getCount() 
    return getlForm().size();


public Formulario getItem(Formulario form) 
    return form;


public long getItemId(int position) 
    return position;


public static class ViewHolder 
    public TextView item;
    public EditText valor;
    public ImageView imgCam;
    public Button listaCerrada;


public View getView(final int position, View convertView, ViewGroup parent) 
    final ViewHolder holder;
    final String marca;
    final String producto;
    int tipo;
    try 
        if (convertView == null) 
            holder = new ViewHolder();
            LayoutInflater vi = (LayoutInflater) ctx
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = vi.inflate(R.layout.row_lista_form, null);

            tipo = getMetrica().getTipo();
            holder.item = (TextView) convertView.findViewById(R.id.item);

            holder.valor = (EditText) convertView.findViewById(R.id.valor);
            holder.valor.setTag(position);

            holder.listaCerrada = (Button) convertView
                    .findViewById(R.id.listaCerrada);
            holder.listaCerrada.setTag(position);

            if (tipo == 1) 
                holder.valor.setVisibility(View.VISIBLE);
                holder.listaCerrada.setVisibility(View.GONE);
             else 
                holder.valor.setVisibility(View.GONE);
                holder.listaCerrada.setVisibility(View.VISIBLE);
                holder.listaCerrada.getTag(position);

            

            holder.imgCam = (ImageView) convertView
                    .findViewById(R.id.cambutton);

            marca = getlForm().get(position).getProducto().getMarca();
            producto = getlForm().get(position).getProducto().getProducto();
            final int productoId = getlForm().get(position).getProducto()
                    .getId();
            String valor = getlForm().get(position).getCantidad();
            String datoValido = getlForm().get(position).getProducto()
                    .getDatoValido();
            if (valor == null || valor.equals("null"))
                valor = "";
            holder.item.setText(marca + "\n" + producto);
            holder.valor.setText(valor);
            holder.listaCerrada.setText(valor);


            holder.imgCam.setOnClickListener(new OnClickListener() 

                @Override
                public void onClick(View v) 
                    prefs.edit().putInt("positionInList", position)
                            .commit();
                    prefs.edit().putInt("metricaId", metricaId).commit();
                    prefs.edit().putString("marca", marca).commit();
                    prefs.edit().putString("producto", producto).commit();
                    prefs.edit().putInt("proyectoproducto", productoId)
                            .commit();
                    takePic(TAKE_PIC_REQUEST);
                
            );

            convertView.setTag(holder);

         else 
            holder = (ViewHolder) convertView.getTag();
            Formulario f = lForm.get(position);
            String cantidad = f.getCantidad();
            holder.valor.setText(cantidad);
            holder.listaCerrada.setText(cantidad);
        

        String fotoName = getlForm().get(position).getImagen();

        if (fotoName != null) 
            Drawable myIcon = ctx.getResources().getDrawable(
                    R.drawable.ic_action_device_access_camera_done);
            holder.imgCam.setImageDrawable(myIcon);
         else 
            // holder.imgCam.setEnabled(true);
            Drawable myIcon = ctx.getResources().getDrawable(
                    R.drawable.ic_action_device_access_camera);
            holder.imgCam.setImageDrawable(myIcon);

        

     catch (Exception e) 
        e.printStackTrace();
    
    return convertView;


// Code : take pic request

private void takePic(int code) 
    MetricaTabs.imageFileUri = ctx.getContentResolver().insert(
            Media.EXTERNAL_CONTENT_URI, new ContentValues());
    Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    ((MetricaTabs) ctx).setResult(Activity.RESULT_OK, i);
    ((MetricaTabs) ctx).startActivityForResult(i, code);



public ArrayList<Formulario> getlForm() 
    return lForm;


public void setlForm(ArrayList<Formulario> lForm) 
    this.lForm = lForm;


public Metrica getMetrica() 
    return metrica;


public void setMetrica(Metrica metrica) 
    this.metrica = metrica;


任何帮助将不胜感激,我不知道如何解决这个问题,在这个问题上花了几天时间...... :(

【问题讨论】:

【参考方案1】:

它单独解决,我不知道是什么原因,今天我运行了应用程序并且它正在工作......使用该代码。我不知道出了什么问题,但是......上帝存在!

【讨论】:

以上是关于PageView 内的 Listview - NotifyDatasetChanged 未调用的主要内容,如果未能解决你的问题,请参考以下文章

Flutter - 如何制作 PageView 和 ListView?

Flutter 小技巧之 ListView 和 PageView 的各种花式嵌套

Flutter 小技巧之 ListView 和 PageView 的各种花式嵌套

采用cocos2d-x lua 的listview 实现pageview的翻页效果之上下翻页效果

如何修复 ListView 生成的错误?

jQuery Mobile Popup 和 ListView,以及 Popup div 内的 Knockout.js 数据绑定 - 不工作