1

やあみんな私は誰かがこのコードがどのように機能しているか、より具体的にはsimpleCursorAdapterに光を当てることができることを望んでいました。完全なプログラムはやることリストであるアプリであり、ユーザーがデータまたは「メモ」を入力し、カーソルとローダーを使用してsqliteデータベースに保存できる非常にシンプルなチュートリアルです。

ですから、私の問題は、それがどのように機能するかを理解するのに苦労している特定の方法があり、その結果、データの表示方法を操作できないことです。問題は、アダプタが表示されているものとは異なるレイアウトをどのように取り込んでいて、すべてをリストビューに表示しているかがわからないという事実にあると思います。

  private void fillData() {

    // Fields from the database (projection)
    // Must include the _id column for the adapter to work
    String[] from = new String[] { TodoTable.COLUMN_SUMMARY };


    // Fields on the UI to which we map
    int[] to = new int[] { R.id.label }; //I don't quite understand but I know it's just a value for the adapter

    getLoaderManager().initLoader(0, null, this);

    adapter = new SimpleCursorAdapter(this, R.layout.todo_row, null, from,  
        to, 0); /*This line specifically I don't understand how it is working. 
            R.layout.todo_row is a near blank xml, used when there are no "todos"
            with no listviews.  R.layout.todo_list has the listview's but when 
            assigned in the adapter it doesn't work.


    setListAdapter(adapter);

  }

全体として、3つのリストビューを並べて作成し、DBからデータを読み取って、遊んでみようとしています。誰かが私を手伝ってくれるなら、それはとてもありがたいです、ありがとう。

R.layout.todo_row

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <ImageView
        android:id="@+id/icon"
        android:layout_width="30dp"
        android:layout_height="24dp"
        android:layout_marginLeft="4dp"
        android:layout_marginRight="8dp"
        android:layout_marginTop="8dp"
        android:src="@drawable/reminder" >
    </ImageView>

    <TextView
        android:id="@+id/label"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="6dp"
        android:lines="1"
        android:text="@+id/TextView01"
        android:textSize="24dp" 
        >
    </TextView>


</LinearLayout> 

およびR.layout.todo_list

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

        <ListView
           android:id="@android:id/list"
            android:layout_width="110dp"
            android:layout_height="200dp" >

        </ListView>

        <ListView
            android:id="@+id/listMiddle"
            android:layout_width="110dp"
            android:layout_height="200dp"
            android:layout_toRightOf="@android:id/list" >
        </ListView>

       <ListView
            android:id="@+id/listRight"
            android:layout_width="110dp"
            android:layout_height="200dp"
            android:layout_toRightOf="@id/listMiddle" >
        </ListView>

    <TextView
        android:id="@android:id/empty"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/no_todos" />

</RelativeLayout> 

クラス全体は以下のとおりです

package de.vogella.android.todos;

import android.app.ListActivity;
import android.app.LoaderManager;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import de.vogella.android.todos.contentprovider.MyTodoContentProvider;
import de.vogella.android.todos.database.TodoTable;

/*
 * TodosOverviewActivity displays the existing todo items
 * in a list
 * 
 * You can create new ones via the ActionBar entry "Insert"
 * You can delete existing ones via a long press on the item
 */

public class TodosOverviewActivity extends ListActivity implements
    LoaderManager.LoaderCallbacks<Cursor> {
  private static final int ACTIVITY_CREATE = 0;
  private static final int ACTIVITY_EDIT = 1;
  private static final int DELETE_ID = Menu.FIRST + 1;
  // private Cursor cursor;
  private SimpleCursorAdapter adapter;
  private SimpleCursorAdapter middleAdapter;
  private SimpleCursorAdapter rightAdapter;



/** Called when the activity is first created. */

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.todo_list);
    this.getListView().setDividerHeight(2);
    fillData();
    registerForContextMenu(getListView());
  }

  // Create the menu based on the XML defintion
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.listmenu, menu);
    return true;
  }

  // Reaction to the menu selection
  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.insert:
      createTodo();
      return true;
    }
    return super.onOptionsItemSelected(item);
  }

  @Override
  public boolean onContextItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case DELETE_ID:
      AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
          .getMenuInfo();
      Uri uri = Uri.parse(MyTodoContentProvider.CONTENT_URI + "/"
          + info.id);
      getContentResolver().delete(uri, null, null);
      fillData();
      return true;
    }
    return super.onContextItemSelected(item);
  }

  private void createTodo() {
    Intent i = new Intent(this, TodoDetailActivity.class);
    startActivity(i);
  }

  // Opens the second activity if an entry is clicked
  @Override
  protected void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);
    Intent i = new Intent(this, TodoDetailActivity.class);
    Uri todoUri = Uri.parse(MyTodoContentProvider.CONTENT_URI + "/" + id);
    i.putExtra(MyTodoContentProvider.CONTENT_ITEM_TYPE, todoUri);

    startActivity(i);
  }



  private void fillData() {

    // Fields from the database (projection)
    // Must include the _id column for the adapter to work
    String[] from = new String[] { TodoTable.COLUMN_SUMMARY };
    String[] middleId = new String[] { TodoTable.COLUMN_ID };

    // Fields on the UI to which we map
    int[] to = new int[] { R.id.label };
    int[] two = new int[] { R.id.label };

    getLoaderManager().initLoader(0, null, this);
    adapter = new SimpleCursorAdapter(this, R.layout.todo_row, null, from,
        to, 0);

    middleAdapter = new SimpleCursorAdapter(this, R.layout.todo_row, null, middleId,
            two, 0);


    setListAdapter(adapter);
   // setListAdapter(middleAdapter);

  }

  @Override
  public void onCreateContextMenu(ContextMenu menu, View v,
      ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    menu.add(0, DELETE_ID, 0, R.string.menu_delete);
  }

  // Creates a new loader after the initLoader () call
  @Override
  public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    String[] projection = { TodoTable.COLUMN_ID, TodoTable.COLUMN_SUMMARY };
    CursorLoader cursorLoader = new CursorLoader(this,
        MyTodoContentProvider.CONTENT_URI, projection, null, null, null);
    return cursorLoader;
  }

  @Override
  public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    adapter.swapCursor(data);
  }

  @Override
  public void onLoaderReset(Loader<Cursor> loader) {
    // data is not available anymore, delete reference
    adapter.swapCursor(null);
  }

} 
4

3 に答える 3

2

ですから、私の問題は、それがどのように機能するかを理解するのに苦労している特定の方法があり、その結果、データの表示方法を操作できないことです。

方法:

adapter = new SimpleCursorAdapter(this, R.layout.todo_row, null, from, to, 0);

さて、このコンストラクターをパラメーターごとに分類してみましょう。

  1. this、コンテキスト。アダプタには、各行のレイアウトを拡張するためのコンテキストが必要です。
  2. R.layout.todo_row、行のレイアウト。カーソル内のすべてのレコードがこのレイアウトで表示されます。(正確にカーソルがどのようfromに表示されるかは、とによって異なりtoます。)
  3. null、カーソル。これは、ListViewに表示されるすべてのデータを保持します。
  4. from、行レイアウトの重要なビューの配列。
  5. to、カーソルの重要な列の配列。
  6. 0、データを更新するタイミングと理由のフラグ。

すべての背後にある秘訣はこれです。4番目の()のIDは、fromそれぞれ2番目のパラメーター(R.layout.todo_row)のビューと一致する必要があります。5番目のパラメータの文字列は、それぞれカーソルの列名と一致する必要があります。各列は1つのビューに表示されるため、4番目(from)と5番目のパラメーター( )は1対1で一致する必要があります。to本当にそれだけです。


あなたが今までに気づいたかもしれないように、このメモ:

R.layout.todo_rowは、ほぼ空白のxmlであり、リストビューのない「todos」がない場合に使用されます。

間違っています、ごめんなさい。カーソルが空のときにメモを表示する場合は、次を追加します。

 <TextView android:id="@android:id/empty"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:text="No data"/>

のドキュメントtodo_list.xmlで説明されているように。TextViewでこの「マジックID」を使用すると、必要に応じてメモが自動的に表示または非表示になります。ListActivity


これらはすべて、最初のListView(ID: `android:id =" @ android:id / list ")のビューとのみ相互作用します。他のListViewを使用するには、新しいカーソルとアダプターを作成する必要があります。お役に立てば幸いです。

于 2013-02-28T01:38:36.273 に答える
0

SimpleCursorAdapterのソースコードは見ていません。ただし、ほとんどの場合、次の2つのことを行っているようです。

  1. fillDataで指定したパラメーターに基づく、データのクエリ。
  2. 結果をループし、テンプレートを使用してリストにデータを入力します。

私のデバッグでは、リストへの入力が非常に効率的であることに気付きました。表示に必要な数の行のみが割り当てられます。スクロールすると、それらを自由に再割り当てするのではなく、リサイクルします。

fillDataコードは適切なようです。何が機能していないかは言わないので、おそらく他の場所にあります。私はonCreateLoaderを使用したことがないので(おそらく使用する必要があります)、コメントすることはできません。

小さな問題が1つありました。R.layout.todo_rowで、orientation属性を忘れてしまいました。

于 2013-02-28T01:42:13.430 に答える
0

コードが正常にコンパイルおよび実行され、何が起こっているのかを知りたいだけだと思います。さて、あなたが知っておく必要があるいくつかのことがあります。1つ目は、ListViewがレイアウトパラメータを受け取らないことです。アクティビティはで行いsetContentViewます。は、アクティビティの「画面」または「外観」を作成するためにR.layout.todo_listのみ使用されTodosOverviewActivityます。つまり、3つのListViewビューを並べて作成します。アクティビティはであるため、IDがListActivityのタイプのエントリを自動的に検索してリストリスナーを自動的に接続します(入力を少し節約するだけです)。したがって、他のリストは、接続するまでほとんどそこに留まります。自分で(同じレイアウトのアイテムに同じIDを使用しないでください)。これらの他のリストにアクセスする必要がある場合は、ListView@android:id/listfindViewByIdアクティビティでメソッドを実行し、必要なリストのIDを検索します。たとえば、次のコマンドを使用してミドルリストにアクセスできます。

ListView middleList = (ListView)this.findById(R.id.listMiddle);

リストができたので、何かを表示する必要があります。リストは完全に空であり、どこかからデータを取り込む必要があります。あなたの場合、データはから取得したCursorオブジェクトから取得されますContentProvider。カーソルには、重要な列が1つだけ含まれTodoTable.COLUMN_SUMMARYています。これは、リストに表示するテキストを含む列です。Cursor問題は、リストにビューを表示して上下にスクロールするだけなので、リストに何をすべきかについての手がかりがないことです。一方Cursor、は、表示したいすべてのデータを持っていますが、aが何であるかについての手がかりはありませんView。ましてや、リストに表示するために、そこに含まれるすべてのデータを1つに入れる方法はありません。今、あなたはSimpleCursorAdapter名前が示すように、これはアダプターです。互換性のないものを連携させるために使用されます。一方にはビューが必要なリストがあり、もう一方には表示するデータを含むカーソルがあるため、各データをビューの一部にマップするアダプターが必要になります。特に4つのSimpleCursorAdapterことをお願いします。1つ目は、リストに表示するビューのレイアウト、つまり、リストアイテムがどのように表示されるかです。これは、R.layout.todo_rowどのビューを作成する必要があるかをアダプターに指示するものです。この場合、アイコンとTextViewIDを持つaのみがありますR.id.labelonLoadFinished次に、メソッド内に設定されているデータを含むカーソルを要求します(nullアダプターが作成されたときです)。第三に、カーソルのどの列が重要かを知りたいのです。これはString[] from内のデータを検索する必要があることを示す配列TodoTable.COLUMN_SUMMARY。最後に、このデータをビューのどこに配置するかを知る必要があります。これには、テキストの表示に使用するint[] toIDが含まれています。TextViewR.id.label

要約すると、アダプターは、カーソルからのデータとビューのレイアウトの間のマップのようなものです。これで、リストに画面に表示するビューが必要になると、アダプターにビューを表示するように求められます。次に、アダプターは、指定したレイアウトからビューをリサイクルまたは作成し、カーソルからレイアウトの各部分のデータをフェッチして、リストに移動して画面に表示できるようにします。

于 2013-02-28T02:07:45.757 に答える