将两个 SQL 列加载到列表视图中但只需要显示第一列 Android

Posted

技术标签:

【中文标题】将两个 SQL 列加载到列表视图中但只需要显示第一列 Android【英文标题】:Loading two SQL columns into a listview but only need to display the first column Android 【发布时间】:2019-08-18 16:30:55 【问题描述】:

我正在使用 sqllite 数据库来存储电话名称和电话号码两列。我正在使用 arrayList 遍历数据并在正在工作的列表视图中显示电话名称,但我还需要遍历同一列表视图下的电话号码列。我只需要在列表视图中显示电话名称。

这是因为当用户在列表视图中选择了项目时,它会显示所选的电话名称和电话号码,目前它仅显示电话名称并且出于明显的原因显示为空白的电话号码。

DataDBAdapter

public long insert(String phonename, String phonenumber)

    ContentValues cv = new ContentValues();
    cv.put(COl_MYTABLE_PHONENAME,phonename);
    cv.put(COL_MYTABLE_PHONENUMBER,phonenumber);

    return mDB.insert(TBL_MYTABLE,null,cv);


    //---------------------------------------------------------------------------
    // Iterating through the database
    //---------------------------------------------------------------------------
    public ArrayList<String> getAllRowsAsList()
    
        Cursor csr = mDB.query(TBL_MYTABLE,null,null,null,null,null,null);
        ArrayList<String> rv = new ArrayList<>();
        while (csr.moveToNext())
        
            rv.add(csr.getString(csr.getColumnIndex(COl_MYTABLE_PHONENAME)));
        
        return rv;
    

选择调制解调器片段

 private void manageListView(Context context)
    
        thelist = dbHelper.getAllRowsAsList();  // Extract the list, just the phone names

        // Only setup the adapter and the ListView if the adapter hasn't been setup
        if(arrayAdapter == null)
        
            // Instantiate the adapter
            arrayAdapter = new ArrayAdapter<>(context,android.R.layout.simple_list_item_1,thelist); //<<<<<<<<<< list included
            display_contacts1.setAdapter(arrayAdapter); //<<<<<<<<<< Tie the adpater to the ListView

            // Set the ListViews OnItemClick Listener
            display_contacts1.setOnItemClickListener(new AdapterView.OnItemClickListener()
            
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id)
                
                    String namedisplay = arrayAdapter.getItem(position); //<<<<<<<<<< this gets the phone name

                    namedisplay = arrayAdapter.getItem(position);

                    Toast.makeText(view.getContext(), namedisplay + " Selected for Communication", Toast.LENGTH_SHORT).show();
                    Toast.makeText(view.getContext(), phoneNo, Toast.LENGTH_SHORT).show();

                
            );
    

【问题讨论】:

【参考方案1】:

问题

使用 ArrayAdapter 只允许传递单个项目,因此除非您使用复杂/杂乱/低效的方法,否则 ArrayAdapter 仅适用于单个值。

修复

您可以使用 ArrayList,其中 your_object 具有所有必需值的成员。即电话号码和电话名称。请注意,除非您使用自定义适配器,否则您应该重写 toString 方法来提取要显示的数据,因为这是标准 ArrayAdapter 使用的。

替代方案(使用 CursorAdapter)

另一种方法是使用光标适配器(例如 SimpleCursorAdapter),然后您可以返回光标并直接使用它。但是,CursorAdapter 需要一个专门命名为 _id 的列(可以使用 BaseColumns._ID)。

Cursor 适配器的一个明显优势是传递给 onItemClick/onItemLongClick 的第四个参数是行的 id(如果使用正确)允许单个值随后获取/更新/删除/传递相应的选定行。

因此,我建议为 ListView 使用 Cursor Adapter,从而获得更全面的答案。

你可能认为我没有这样的专栏。但是,您可以使用通常隐藏的 rowid 列并动态创建名为 _id 的列。

您可以在数据库助手 (DataDBAdapter) 中有一个方法,例如:-

public Cursor getAllRowsAsCursor()

    String[] columns = new String[]"rowid AS " + BaseColumns._ID,"*"
    return = mDB.query(TBL_MYTABLE,null,null,null,null,null,null)

ManageList 方法可以是:-

private void manageListView(Context context) 

    myCursor = dbhelper.getAllRowsAsCursor();

    // Only setup the adapter and the ListView if the adapter hasn't been setup
    if(arrayAdapter == null)
    
        // Instantiate the adapter
        arrayAdapter = new SimpleCursorAdapter(context,android.R.layout.simple_list_item_1,myCursor,new String[]DataAdapter.COl_MYTABLE_PHONENAME,newint[]android.R.id.text1,0);
        display_contacts1.setAdapter(arrayAdapter); //<<<<<<<<<< Tie the adpater to the ListView

        // Set the ListViews OnItemClick Listener
        display_contacts1.setOnItemClickListener(new AdapterView.OnItemClickListener()
        
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id)
            
                String namedisplay = arrayAdapter.getItem(position); //<<<<<<<<<< this gets the phone name

                String phonenumber = myCursor,getString(myCursor.getColumnIndex(DataAdapter.COL_MYTABLE_PHONENUMBER);

                Toast.makeText(view.getContext(), namedisplay + " Selected for Communication", Toast.LENGTH_SHORT).show();
                Toast.makeText(view.getContext(), phonenumber, Toast.LENGTH_SHORT).show();

            
        );
     else 
        arrayAdapter.swapCursor(myCursor);
    

注意事项

MyCursor 将被声明为类变量,例如Cursor MyCursor; 代替 ArrayAdapter&lt;String&gt; arrayAdapter; 你会有 SimpleCursorAdapter arrayAdapter; 以上为原理代码,未经测试,可能存在错误和/或遗漏。

工作示例

以下是基于上一个问题中的代码的代码(这似乎是后续问题)。它有两个旧的 ListView 和一个使用 SimpleCursorAdapter 的新 ListView。单击项目会显示电话号码和 ID。 Lon 单击一个项目会删除该项目(刷新两个 ListView)。

DataDBAdapter.java 有两个新方法(所以添加这些):-

//<<<<<<<<<< ADDED
public Cursor getAllRowsAsCursor() 
    return mDB.query(TBL_MYTABLE,null,null,null,null,null,null);


public int delete(long id) 
    String whereclause = COL_MYTABLE_ID + "=?";
    String[] whereargs = new String[]String.valueOf(id);
    return mDB.delete(TBL_MYTABLE,whereclause,whereargs);

SelectModemFragment.java 现在是:-

public class SelectModemFragment extends Fragment 

    private SelectModemViewModel mViewModel;
    ListView display_contacts1;
    ArrayAdapter<String> arrayAdapter;
    ArrayList<String> thelist;
    DataDBAdapter dbhelper;

    //<<<<<<<<<< ADDED
    ListView display_contacts2;
    SimpleCursorAdapter sca;
    Cursor MyCursor;

    public static SelectModemFragment newInstance() 
        return new SelectModemFragment();
    

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) 
        View view = inflater.inflate(R.layout.select_modem_fragment, container, false);
        display_contacts1 = view.findViewById(R.id.lv001); //<<<<<<<<<< top listview ArrayAdapter<String>
        display_contacts2 = view.findViewById(R.id.lv002);

        dbhelper = new DataDBAdapter(view.getContext());
        AddSomeData();
        manageListView(view.getContext());
        manageListView2();
        return view;
    

    @Override
    public void onActivityCreated(Bundle savedInstanceState) 
        super.onActivityCreated(savedInstanceState);
        mViewModel = ViewModelProviders.of(this).get(SelectModemViewModel.class);
        // TODO: Use the ViewModel
    

    //Sets up the ListView if not already setup
    private void manageListView(Context context) 
        thelist = dbhelper.getAllRowsAsList(); //<<<<<<<<<< extract the list (just the phone names) from the database

        // Only setup the adapter and the ListView if the adapter hasn't been setup
        if (arrayAdapter == null) 
            // Instantiate the adapter
            arrayAdapter = new ArrayAdapter<>(context,android.R.layout.simple_list_item_1,thelist); //<<<<<<<<<< list included
            display_contacts1.setAdapter(arrayAdapter); //<<<<<<<<<< Tie the adpater to the ListView

            // Set the ListViews OnItemClick Listener
            display_contacts1.setOnItemClickListener(new AdapterView.OnItemClickListener() 
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
                    String name = arrayAdapter.getItem(position); //<<<<<<<<<< this gets the phone name
                    Toast.makeText(view.getContext(),"You clicked the phone named " + name,Toast.LENGTH_SHORT).show();
                
            );
         else 
            //<<<<<<<<<< MODIFIED to cope with changes (needs to rebuild the array within the adpater)
            arrayAdapter.clear();
            for (String s: thelist) 
                arrayAdapter.add(s);
            
            arrayAdapter.notifyDataSetChanged();
        
    

    //<<<<<<<<<< ADDED FOR CursorAdapter
    private void manageListView2() 
        MyCursor = dbhelper.getAllRowsAsCursor();
        if (sca == null) 
            sca = new SimpleCursorAdapter(
                    getContext(),
                    android.R.layout.simple_list_item_1,
                    MyCursor,
                    new String[]DataDBAdapter.COl_MYTABLE_PHONENAME,
                    new int[]android.R.id.text1,
                    0
            );
            display_contacts2.setAdapter(sca);
            display_contacts2.setOnItemClickListener(new AdapterView.OnItemClickListener() 
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
                    Toast.makeText(view.getContext(),
                            "You Clicked the phone name " +
                                    MyCursor.getString(MyCursor.getColumnIndex(DataDBAdapter.COl_MYTABLE_PHONENAME)) +
                                    ". The phonenumber is " +
                                    MyCursor.getString(MyCursor.getColumnIndex(DataDBAdapter.COL_MYTABLE_PHONENUMBER)) +
                                    ". The ID (as passed) is " + String.valueOf(id) +
                                    ". The ID (from Cursor) is " + String.valueOf(MyCursor.getLong(MyCursor.getColumnIndex(DataDBAdapter.COL_MYTABLE_ID)))
                            ,
                            Toast.LENGTH_SHORT).show();
                
            );
            //<<<<<<<<<< EXTRA delete row on long click
            display_contacts2.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() 
                @Override
                public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) 
                    dbhelper.delete(id);
                    manageListView2();
                    manageListView(getContext());
                    return true;
                
            );
         else 
            sca.swapCursor(MyCursor);
        
    

    // Add some testing data (only if none already exists)
    private void AddSomeData() 
        if (DatabaseUtils.queryNumEntries(dbhelper.getWritableDatabase(),DataDBAdapter.TBL_MYTABLE) < 1) 
            dbhelper.insert("Phone 1", "0000000000");
            dbhelper.insert("Phone 2", "1111111111");
        
    

    @Override
    public void onResume() 
        super.onResume();
        manageListView2();
        manageListView(getContext());
    

    @Override
    public void onDetach() 
        super.onDetach();
        MyCursor.close();
    

【讨论】:

@SahilBora 这是因为错字 myCursor 应该是 MyCursor。附言没有意识到代码来自我的答案。我即将用两个示例来编辑问题,即两个单独的 ListView(ArrayAdapter 和 CursorAdapter)。后者也可以长按删除一行并刷新两个列表。 一切都好,我刚刚得到了代码。我已将答案标记为正确:)

以上是关于将两个 SQL 列加载到列表视图中但只需要显示第一列 Android的主要内容,如果未能解决你的问题,请参考以下文章

Android OnItemClick 无法将加载的 SQL 数据库加载到列表视图中

如何将显示的 sql 数据加载到 wpf 可滚动列表视图中?大型集合(20k+)而不会遇到内存问题?

如何使用自定义适配器将整数添加到列表视图

将pdf文件以图片形式添加到word中

将 CSV 文件从 S3 加载到 Snowflake 时出现 SQL 编译错误

在 sql-server 中创建一个允许输入新记录的视图