2015-06-26 6 views
7

Das Problem ist, ich benutze es nicht wie ich sollte, ich lade die Daten von in arrayLists und dann verwenden Sie die Listen.Wie kann ich einen CursorLoader in einem ViewPager verwenden?

Ich fand dieses Tutorial, das zeigt, wie man ein cursorLoader mit einem viewPager verwendet, aber ich verstehe nicht, wie man es tatsächlich geschieht.

http://tumble.mlcastle.net/post/25875136857/bridging-cursorloaders-and-viewpagers-on-android

Ich habe ein Fragment, das wie folgt aussieht:

public class FirstFragment extends Fragment { 
    MapView mapView; 
    GoogleMap map; 
    // Store instance variables 
    private String email,about,imagepath,latitude,longitude; 
    Button getDirections; 

    // newInstance constructor for creating fragment with arguments 
    public static FirstFragment newInstance(String email,String about,String imagepath, String latitude, String longitude) { 
     FirstFragment fragmentFirst = new FirstFragment(); 
     Bundle args = new Bundle(); 
     args.putString("email", email); 
     args.putString("about", about); 
     args.putString("imagepath", imagepath); 
     args.putString("latitude", latitude); 
     args.putString("longitude", longitude); 
     fragmentFirst.setArguments(args); 
     return fragmentFirst; 
    } 

    // Store instance variables based on arguments passed 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     email = getArguments().getString("email"); 
     about = getArguments().getString("about"); 
     imagepath = getArguments().getString("imagepath"); 
     latitude = getArguments().getString("latitude"); 
     longitude = getArguments().getString("longitude"); 
    } 

    // Inflate the view for the fragment based on layout XML 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          final Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.zzfragment_pager_items, container, false); 
     ImageView imageView = (ImageView) view.findViewById(R.id.listpager_imageView); 
     TextView about = (TextView) view.findViewById(R.id.listpager_text); 
     TextView emaill = (TextView) view.findViewById(R.id.listpager_title); 
     about.setText(this.about); 
     emaill.setText(this.email); 

     ImageLoader imageLoader = ImageLoader.getInstance(); 
     DisplayImageOptions options = new DisplayImageOptions.Builder().cacheInMemory(true) 
       .cacheOnDisc(true).resetViewBeforeLoading(true) 
       .considerExifParams(true) 
       .build(); 
     imageLoader.getInstance().displayImage(imagepath, imageView, options); 

     getDirections = (Button) view.findViewById(R.id.getdirections); 

     getDirections.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 

       String strUri = "http://maps.google.com/maps?q=loc:" + latitude + "," + longitude + " (" + email + ")"; 
       Intent mapIntent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(strUri)); 

       mapIntent.setClassName("com.google.android.apps.maps", "com.google.android.maps.MapsActivity"); 

       getActivity().startActivity(mapIntent); 

      } 
     }); 

//  View v = inflater.inflate(R.layout.listviewtopager, container, false); 
     // Gets the MapView from the XML layout and creates it 
     mapView = (MapView) view.findViewById(R.id.mapview); 
     mapView.onCreate(savedInstanceState); 

     // Gets to GoogleMap from the MapView and does initialization stuff 
     map = mapView.getMap(); 
     map.getUiSettings().setMyLocationButtonEnabled(false); 
     map.setMyLocationEnabled(true); 

     // Needs to call MapsInitializer before doing any CameraUpdateFactory calls 
     MapsInitializer.initialize(this.getActivity()); 

     // Updates the location and zoom of the MapView 
     CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(Double.parseDouble(latitude), Double.parseDouble(longitude)), 10); 
     map.animateCamera(cameraUpdate); 

     return view; 
    } 

    @Override 
    public void onResume() { 
     mapView.onResume(); 
     super.onResume(); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     mapView.onDestroy(); 
    } 

    @Override 
    public void onLowMemory() { 
     super.onLowMemory(); 
     mapView.onLowMemory(); 
    } 
} 

Und ich war es in dieser Klasse aufrufen:

public class ViewPagerFragment extends FragmentActivity implements 
     LoaderManager.LoaderCallbacks<Cursor>{ 

    ArrayList<String> e 

mail = new ArrayList<String>(); 
ArrayList<String> about = new ArrayList<String>(); 

ArrayList<String> imagepath = new ArrayList<String>(); 

ArrayList<String> latitude = new ArrayList<String>(); 

ArrayList<String> longitude = new ArrayList<String>(); 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_view_pager_fragment); 
    getLoaderManager().initLoader(1, null, this); 
} 

private SmartFragmentStatePagerAdapter adapterViewPager; 

// Extend from SmartFragmentStatePagerAdapter now instead for more dynamic ViewPager items 
public static class MyPagerAdapter extends SmartFragmentStatePagerAdapter { 
    private final ArrayList<String> email; 
    private final ArrayList<String> about; 
    private final ArrayList<String> imagepath; 
    private final ArrayList<String> latitude; 
    private final ArrayList<String> longitude; 
    private int listPosition; 

    public MyPagerAdapter(FragmentManager fragmentManager,ArrayList<String> email,ArrayList<String> about, ArrayList<String> imagepath,ArrayList<String> latitude,ArrayList<String> longitude,int lPosition) { 
     super(fragmentManager); 
     this.imagepath=imagepath; 
     this.email=email; 
     this.about = about; 
     this.latitude= latitude; 
     this.longitude = longitude; 
     listPosition = lPosition; 
    } 

// Returns total number of pages 
@Override 
public int getCount() { 
    return email.size(); 
} 



// Returns the fragment to display for that page 
    @Override 
     public Fragment getItem(int position) { 
//   return FirstFragment.newInstance(listPosition+position, email.get(listPosition+position)); 
      return FirstFragment.newInstance(email.get(position), about.get(position),imagepath.get(position),latitude.get(position),longitude.get(position)); 
    } 

    // Returns the page title for the top indicator 
    @Override 
    public CharSequence getPageTitle(int position) { 
     return "Page " + position; 
    } 

} 

@Override 
public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
    String[] projection = 
      { 
        ActivitiesTable.KEY_EMAIL, 
        ActivitiesTable.KEY_ABOUT, 
        ActivitiesTable.KEY_IMAGEPATH, 
        ActivitiesTable.KEY_LATITUDE, 
        ActivitiesTable.KEY_LONGITUTDE 

      }; 
    CursorLoader cursorLoader = new CursorLoader(this, NameContentProvider.NAME_ACTIVITIES_URI, projection, 
      null, null, null); 
    return cursorLoader; 
} 

@Override 
public void onLoadFinished(android.content.Loader<Cursor> loader, Cursor cursor) { 
    if (cursor != null && cursor.getCount() > 0) { 
     cursor.moveToFirst(); 
     do { 
      email.add(cursor.getString(cursor 
        .getColumnIndexOrThrow("email"))); 
      about.add(cursor.getString(cursor 
        .getColumnIndexOrThrow("about"))); 
      imagepath.add(cursor.getString(cursor 
        .getColumnIndexOrThrow("imagepath"))); 
      latitude.add(cursor.getString(cursor 
        .getColumnIndexOrThrow("serverLatitude"))); 
      longitude.add(cursor.getString(cursor 
        .getColumnIndexOrThrow("serverLongitude"))); 
     } while (cursor.moveToNext()); 
    } 

    int listPosition = getIntent().getExtras().getInt("position"); 


    ViewPager vpPager = (ViewPager) findViewById(R.id.vpPager); 
    adapterViewPager = new MyPagerAdapter(getSupportFragmentManager(),email,about,imagepath,latitude,longitude,listPosition); 
    vpPager.setAdapter(adapterViewPager); 
    vpPager.setCurrentItem(listPosition); 

} 

@Override 
public void onLoaderReset(android.content.Loader<Cursor> loader) { 



    } 
} 

Wie kann ich den Code ändern, die viewPager zu verwenden mit dem Loader direkt mit diesem Tutorial, anstatt alles in Listen zu speichern und dann die Listen zu verwenden?

+0

Zunächst, anstatt sich mit 5 verschiedenen ArrayLists zu beschäftigen, warum erstellen Sie nicht einfach eine Klasse, die alle 5 Werte repräsentiert und diese Objekte in eine einzige ArrayList legt? Dieser Ansatz würde Ihren Code viel sauberer machen und für mich ist das Ergebnis in Ordnung, dann –

+0

Ich möchte die Listen nicht mehr verwenden. Ich habe bereits einen Weg gefunden, die Daten direkt vom cursorLoader zu verwenden, aber es verwendet einige veraltete Methoden. Dieser sieht besser aus, aber ich habe keine Ahnung, wie es funktioniert –

+0

Die Methode, die ich benutze, die Daten direkt aus dem Loader ohne die Arraylists lädt erweitert pagerAdapter und verwendet InstantiateItem und DestroyItem, die veraltet sind. Ich mag die Methode, die ich hier veröffentlicht habe, aber ich konnte es nicht funktionieren lassen. –

Antwort

1

ich nicht kommentieren kann, so dass ich eine Antwort ich schreibe ..

Sie haben eine Aktivität, die LoaderCallbacks<Cursor> implementiert. Ihre Aktivität erhält onLoadFinished Rückruf, wenn Ihre Daten geladen werden. Innerhalb dieser Methode haben Sie eine Cursor, die in Ihrem ViewPager angezeigt werden sollte. Um die Daten von Cursor anzuzeigen, rufen Sie die Methode swapCursor auf dem Adapter an. Erstellen Sie also nicht jedes Mal einen Adapter, wenn Sie Daten laden. Erstellen Sie es einmal und rufen Sie dann swapCursor darauf an.

Auch nicht finden ViewPager jedes Mal - findViewById ist eine schwere Operation, sollte es durchgeführt werden, sobald die Ansicht Hierarchie erstellt wird.

Also, Ihre onLoadFinished wird wie folgt aussehen:

@Override 
public void onLoadFinished(android.content.Loader<Cursor> loader, Cursor cursor) { 
    if (adapterViewPager == null) { 
     adapterViewPager = new MyPagerAdapter(getSupportFragmentManager(), cursor); 
     vpPager.setAdapter(adapterViewPager); 
    } else { 
     adapterViewPager.swapCursor(cursor); 
    } 
} 
0

Statt halten 5-Arrays von Daten nur halten Sie die Cursor in der Ansicht Pager-Adapter und die Daten vom Cursor laden, wenn benötigt wird. Auf diese Weise wird die Benutzeroberfläche nicht blockiert, wenn Sie viele Elemente in Ihrem Cursor haben.

Sie können auch ein Verfahren zum Austausch des Cursors hinzufügen und mitteilen, dass Daten geändert und viewpager wird statt neu zu erstellen und Anbringen des Adapters jedes Mal (genau wie in der Link, den Sie erwähnen)

Die MyPagerAdapter aktualisiert wie folgt aussehen sollte:

Cursor cursor; 

// Returns total number of pages 
@Override 
public int getCount() { 
    return cursor==null?0:cursor.getCount(); 
} 

// Returns the fragment to display for that page 
@Override 
public Fragment getItem(int position) { 
    // position the cursor first 
    cursor.moveToPosition(position); 

    // read each field 
    String email = cursor.getString(cursor 
        .getColumnIndexOrThrow("email")); 
    ... 
    return FirstFragment.newInstance(email, ...); 
} 

public void swapCursor(Cursor cursor) { 
    this.cursor = cursor; 
    // notify that data has changed and viewpager needs to be refreshed 
    notifyDataSetChanged(); 
} 

nicht einmal den Lader zu reinigen vergessen zurückgesetzt wird

@Override 
public void onLoaderReset(android.content.Loader<Cursor> loader) { 
    adapterViewPager.swapCursor(null) 
} 
1

die erste würde ich tun, wenn Ich war in dir, um eine Modellklasse zu erstellen, die die Information enthält, die in deinem Cursor enthalten ist.

public class Information implements Parcelable { 

    public String imagepath; 
    public String email; 
    public String about; 
    public String latitude; 
    public String longitude; 


protected Information(Parcel in) { 
    imagepath = in.readString(); 
    email = in.readString(); 
    about = in.readString(); 
    latitude = in.readString(); 
    longitude = in.readString(); 
} 

@Override 
public int describeContents() { 
    return 0; 
} 

@Override 
public void writeToParcel(Parcel dest, int flags) { 
    dest.writeString(imagepath); 
    dest.writeString(email); 
    dest.writeString(about); 
    dest.writeString(latitude); 
    dest.writeString(longitude); 
} 

@SuppressWarnings("unused") 
public static final Parcelable.Creator<Information> CREATOR = new Parcelable.Creator<Information>() { 
    @Override 
    public Information createFromParcel(Parcel in) { 
     return new Information(in); 
    } 

    @Override 
    public Information[] newArray(int size) { 
     return new Information[size]; 
    } 
}; 
} 

Und das ist schon das meiste davon.Die zweite Sache, die ich tun würde, ist, zwei Hilfsmethoden zu erstellen, eine zum Erstellen einer Instanz dieser Klasse, zum Lesen der Daten vom Cursor und eine weitere zum Erstellen einer Sammlung.

public static Information createInfoFromCursor(Cursor c) { 
     Information info = new Information(); 
     info.email = cursor.getString(cursor 
        .getColumnIndexOrThrow("email"))); 
     info.about = cursor.getString(cursor 
        .getColumnIndexOrThrow("about"))); 
     info.imagepath =(cursor.getString(cursor 
        .getColumnIndexOrThrow("imagepath"))); 
     info.latitude = (cursor.getString(cursor 
        .getColumnIndexOrThrow("serverLatitude"))); 
     info.longitude = (cursor.getString(cursor 
        .getColumnIndexOrThrow("serverLongitude"))); 
     return info; 
    } 

und

public static ArrayList<Information> createInfoListFromCursor(Cursor c) { 
    ArrayList<Information> info = new ArrayList<>(); 
    while(c.moveToNext()) { 
     info.add(createInfoFromCursor()); 
    } 
    return info; 
} 

jetzt können Sie entscheiden, die Cursor zur Verfügung zu stellen, oder die ArrayList<Information>, an den Adapter. Wenn Sie die Cursor passieren entscheiden, in Ihrem Adapter haben Sie

Cursor cursor; 

public MyPagerAdapter(FragmentManager fragmentManager,Cursor c) { 
    super(fragmentManager); 
    cursor = c; 
} 


@Override 
public Fragment getItem(int position) { 
    cursor.moveAtPosition(position); 
    Information info = createInfoFromCursor(cursor); 
    // create a version of `newInstance` that takes an Information object 
    return FirstFragment.newInstance(info); 
} 

@Override 
public int getCount() { 
    return cursor == null ? 0 : cursor.getCount(); 
}  

public Cursor swapCursor(Cursor newCursor) { 
    if (newCursor == cursor) { 
     return null; 
    } 
    cursor = newCursor; 
    if (newCursor != null) { 
     notifyDataSetChanged(); 
    } 
    return oldCursor; 
} 

in Ihrer Aktivität, eine Instanz des Adapters erstellen, einen Null-Cursor vorbei, und halten Sie sich als Mitglied classe. Wenn onLoadFinished genannt wird, verwenden Sie diese Referenz swapCursor, rufen die Adapter der Datenmenge

0

zu aktualisieren Wenn Sie sich für ein gutes einfaches Beispiel suchen, wie eine ViewPager mit Fragmenten von einem Cursor zu füllen, Blick auf den Code von this Activity I schrieb für die FOSDEM Companion App.

Hinweis: Sie sollten es vermeiden, eine Karte in einen ViewPager zu platzieren, da Touch-Ereignisse vom MapView abgefangen werden und der Benutzer nicht zur nächsten oder vorherigen Seite wischen kann.

Verwandte Themen