如何使用 viewpager 和片段为我的 ListView 设置适配器

Posted

技术标签:

【中文标题】如何使用 viewpager 和片段为我的 ListView 设置适配器【英文标题】:How to set an adapter to my ListView with a viewpager and fragment 【发布时间】:2016-11-21 17:32:55 【问题描述】:

我的代码中出现以下错误:

FATAL EXCEPTION: main
                                                                                      Process: com.herprogramacin.hermosaprogramacion, PID: 6541
                                                                                      java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference
                                                                                          at com.herprogramacin.hermosaprogramacion.UI.MainActivity$LoadData.onPostExecute(MainActivity.java:215)
                                                                                          at 

com.herprogramacin.hermosaprogramacion.UI.MainActivity$LoadData.onPostExecute(MainActivity.java:195)
                                                                                          at android.os.AsyncTask.finish(AsyncTask.java:651)
                                                                                          at android.os.AsyncTask.access$500(AsyncTask.java:180)
                                                                                          at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
                                                                                          at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                          at android.os.Looper.loop(Looper.java:158)

我正在使用我的 Activity 的以下代码来获取提要,一旦获得提要,我就使用函数 LoadData 将适配器设置为视图。

 public class MainActivity extends AppCompatActivity 

    private static final String TAG = MainActivity.class.getSimpleName();

    public static final String URL_FEED = "http://www.forbes.com/most-popular/feed";

    private ListView listView;

    private FeedAdapter adapter;

    /*
    ViewPager
     */

    private Toolbar toolbar;
    private TabLayout tabLayout;
    private ViewPager viewPager;
    private ViewPagerAdapter viewPagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Obtener la lista
        listView = (ListView)findViewById(R.id.lista);

        ConnectivityManager connMgr = (ConnectivityManager)
                getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) 
            VolleySingleton.getInstance(this).addToRequestQueue(
                    new XmlRequest<>(
                            URL_FEED,
                            Rss.class,
                            null,
                            new Response.Listener<Rss>() 
                                @Override
                                public void onResponse(Rss response) 
                                    // Caching
                                    FeedDatabase.getInstance(MainActivity.this).
                                            sincronizarEntradas(response.getChannel().getItems());
                                    // Carga inicial de datos...
                                    new LoadData().execute();
                                
                            ,
                            new Response.ErrorListener() 
                                @Override
                                public void onErrorResponse(VolleyError error) 
                                    Log.d(TAG, "Error Volley: " + error.getMessage());
                                
                            
                    )
            );
         else 
            Log.i(TAG, "La conexi�n a internet no est� disponible");
            adapter= new FeedAdapter(
                    this,
                    FeedDatabase.getInstance(this).obtenerEntradas(),
                    SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
            listView.setAdapter(adapter);
        


        /*
        Assigning view variables to thier respective view in xml
        by findViewByID method
         */

        toolbar = (Toolbar) findViewById(R.id.tool_bar);
        tabLayout = (TabLayout) findViewById(R.id.tabs);
        viewPager = (ViewPager) findViewById(R.id.viewpager);

        /*
        Creating Adapter and setting that adapter to the viewPager
        setSupportActionBar method takes the toolbar and sets it as
        the default action bar thus making the toolbar work like a normal
        action bar.
         */
        viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
        viewPager.setAdapter(viewPagerAdapter);
        setSupportActionBar(toolbar);

        /*
        TabLayout.newTab() method creates a tab view, Now a Tab view is not the view
        which is below the tabs, its the tab itself.
         */

        final TabLayout.Tab noticas = tabLayout.newTab();
        final TabLayout.Tab eventos = tabLayout.newTab();
        final TabLayout.Tab trabajo = tabLayout.newTab();

        /*
        Setting Title text for our tabs respectively
         */

        noticas.setText("Noticias");
        eventos.setText("Eventos");
        trabajo.setText("Trabajo");

        /*
        Adding the tab view to our tablayout at appropriate positions
        As I want home at first position I am passing home and 0 as argument to
        the tablayout and like wise for other tabs as well
         */
        tabLayout.addTab(noticas, 0);
        tabLayout.addTab(eventos, 1);
        tabLayout.addTab(trabajo, 2);

        /*
        TabTextColor sets the color for the title of the tabs, passing a ColorStateList here makes
        tab change colors in different situations such as selected, active, inactive etc

        TabIndicatorColor sets the color for the indiactor below the tabs
         */

//        tabLayout.setTabTextColors(ContextCompat.getColorStateList(this, R.color.tab_selector));
//        tabLayout.setSelectedTabIndicatorColor(ContextCompat.getColor(this, R.color.indicator));

        /*
        Adding a onPageChangeListener to the viewPager
        1st we add the PageChangeListener and pass a TabLayoutPageChangeListener so that Tabs Selection
        changes when a viewpager page changes.
         */

        viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));

    

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) 
            return true;
        

        return super.onOptionsItemSelected(item);
    

    public class LoadData extends AsyncTask<Void, Void, Cursor> 

        @Override
        protected Cursor doInBackground(Void... params) 
            // Carga inicial de registros
            return FeedDatabase.getInstance(MainActivity.this).obtenerEntradas();

        

        @Override
        protected void onPostExecute(Cursor cursor) 
            super.onPostExecute(cursor);

            // Crear el adaptador
            adapter = new FeedAdapter(
                    MainActivity.this,
                    cursor,
                    SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);

            // Relacionar la lista con el adaptador
            listView.setAdapter(adapter);
        
    


这是我的 ViewPager

public class ViewPagerAdapter extends FragmentStatePagerAdapter 

    public ViewPagerAdapter(FragmentManager fm) 
        super(fm);
    

    @Override
    public Fragment getItem(int position) 
        return new TabFragment();    
    

    @Override
    public int getCount() 
        return 3;           // As there are only 3 Tabs
    


以及我使用 ListFragment 实现列表视图的 Fragment

public class TabFragment extends ListFragment 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
        return inflater.inflate(R.layout.tabs, container, false);
    

当我在我的活动中将适配器设置为 listview 时,这似乎是一个问题。我需要在我的 MainActivity 中设置它,因为有我的 LoadData 函数。我应该在我的片段中使用适配器吗?如何?那我怎么实现 LoadData 呢?

谢谢

编辑:

这是我的 tabs.xml,我在其中获取“lista”id

<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_
          android:layout_
          android:id="@+id/lista"
          android:divider="@null"
          android:dividerHeight="0dp"
          android:background="#F1F5F8"
          android:padding="6dp"/>

编辑 2:

我想我应该在 LoadData 中创建寻呼机并发送一个带有“新”功能的 Bundle,然后再将 args 从 viewpager 发送到片段。我试过了,但创建捆绑包时出错。

这是我的 feedAdapter。

public class FeedAdapter extends CursorAdapter 

/*
Etiqueta de Depuración
 */
private static final String TAG = FeedAdapter.class.getSimpleName();

/**
 * View holder para evitar multiples llamadas de findViewById()
 */
static class ViewHolder 
    TextView titulo;
    TextView descripcion;

    int tituloI;
    int descripcionI;


public FeedAdapter(Context context, Cursor c, int flags) 
    super(context, c, flags);



public View newView(Context context, Cursor cursor, ViewGroup parent) 
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());

    View view = inflater.inflate(R.layout.item_layout, null, false);

    ViewHolder vh = new ViewHolder();

    // Almacenar referencias
    vh.titulo = (TextView) view.findViewById(R.id.titulo);
    vh.descripcion = (TextView) view.findViewById(R.id.descripcion);

    // Setear indices
    vh.tituloI = cursor.getColumnIndex(ScriptDatabase.ColumnEntradas.TITULO);
    vh.descripcionI = cursor.getColumnIndex(ScriptDatabase.ColumnEntradas.DESCRIPCION);

    view.setTag(vh);

    return view;


public void bindView(View view, Context context, Cursor cursor) 

    final ViewHolder vh = (ViewHolder) view.getTag();

    // Setear el texto al titulo
    vh.titulo.setText(cursor.getString(vh.tituloI));

    // Obtener acceso a la descripción y su longitud
    int ln = cursor.getString(vh.descripcionI).length();
    String descripcion = cursor.getString(vh.descripcionI);

    // Acortar descripción a 77 caracteres
     vh.descripcion.setText(descripcion);



如果我使用 adapter=new FeedAdapter(context,cursor,flag),我必须在捆绑包中使用什么样的“放置”? .putserializable,.putString?

// Crear el adaptador
            adapter = new FeedAdapter(
            MainActivity.this,
            cursor,
            SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
    Bundle arguments = new Bundle();
    arguments.put(adapter);

    viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), arguments);
    viewPager.setAdapter(viewPagerAdapter);

【问题讨论】:

listView = (ListView)findViewById(R.id.lista); 之后,你能做一个if(listView == null) 检查吗?确保 xml 中的 id 与您调用的内容相匹配 (lista) 你是对的。我做了 if(listView == null) System.out.println("There is not listView");并且它可以工作,所以这意味着它还没有创建或者什么? 您也可以分享您的 .xml 文件吗? findViewById 如果找不到,则返回 null 我用那个 xml 编辑了我的原始帖子。我找不到解决方案 【参考方案1】:

您需要将 ListViewtabs.xml 移动到 activity_main.xml(当您调用 findViewById 时,它正在寻找它。然后, 将&lt;ListView android:id="@+id/lista" 更改为&lt;ListView android:id="@android:id/list"。更多信息可以在here找到。

如果xml文件需要自己做,可以参考这个SOanswer。

【讨论】:

我必须使用该 xml,因为我正在使用寻呼机适配器,并且选项卡将是框架的 xml。非常感谢该线程的链接。【参考方案2】:
lv.setAdapter(new ArrayAdapter<String>(getActivity().getApplicationContext(), R.layout.my_layout, R.id.just_an_id, MyList1));

这是我用于片段列表的适配器,效果很好

【讨论】:

您使用扩展 ListFragment 还是仅使用 Fragment?

以上是关于如何使用 viewpager 和片段为我的 ListView 设置适配器的主要内容,如果未能解决你的问题,请参考以下文章

如何在 viewpager 中显示 2 个片段

如何从(和替换)TabLayout 和 ViewPager 移动到新片段?

滑动 ViewPager 时如何清除片段相关状态

选择片段 A 时如何在 ViewPager 上不一起启动所有片段

当 ViewPager 中的片段出现和消失时如何执行一些代码

如何使用 ViewPager 显示相同的片段,但每次加载不同的数据?