2013-04-22 7 views
8

Ich lese etwas mit AsyncTaskLoader, damit ich die Kontaktliste mit dieser Technik laden kann. Der Code funktioniert nur, wenn ich die Rückrufe von einer Klasse implementiere, die Fragment wie in MyLoader extends Fragment implements LoaderCallbacks<ArrayList<Contact>> erweitert. Gibt es eine andere Art und Weise? Alles, was ich wirklich brauche, ist die Kontaktliste (Name, Telefon, Thumbnail), die ich an mein Backend senden kann. Wenn ich zum Beispiel versuche, Context zu verwenden, da ich das von jeder Aktivität erhalten kann, indem ich einfach mache, kann der Code nicht einmal kompilieren. Mit dem Kontext meine ichVerwenden von LoaderCallbacks ohne Fragment

context.getLoaderManager().initLoader(1, null, this); 
//I already changed to Fragment so don't really remember the exact ".context" line. 
//But someone who has done this will understand the snippet. 

BTW: Ich verwende mehrere Referenzen. Einer ist http://developer.android.com/reference/android/content/AsyncTaskLoader.html.

FRAGE (wieder): Kann ich AsyncTaskLoader ohne Fragment oder FragmentActivity verwenden?

Der Code, der mit dem Fragment WORKS:

package com.example.contactpreload.utils; 

import java.util.ArrayList; 

import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.LoaderManager.LoaderCallbacks; 
import android.support.v4.content.Loader; 

public class LoadingContacts extends Fragment implements LoaderCallbacks<ArrayList<Contact>> { 
    ArrayList<Contact> loadedContacts; 
    static Fragment fragmentActivity; 

    public static LoadingContacts newInstance(int arg) { 

     LoadingContacts f = new LoadingContacts(); 
     Bundle bundle = new Bundle(); 
     bundle.putInt("index", arg); 
     f.setArguments(bundle); 
     fragmentActivity = new Fragment(); 
     return f; 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     System.out.println("onCreate()"); 
     int mIndex = getArguments().getInt("index"); 
     System.out.println(mIndex); 
    } 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
     super.onActivityCreated(savedInstanceState); 

     System.out.println("onActivityCreated()"); 
     getLoaderManager().initLoader(1, null, this); 
    } 

    @Override 
    public Loader<ArrayList<Contact>> onCreateLoader(int arg0, Bundle arg1) { 

     System.out.println("onCreateLoader()"); 
     return new ContactsLoader(getActivity()); 
    } 

    @Override 
    public void onLoadFinished(Loader<ArrayList<Contact>> loader, ArrayList<Contact> data) { 
     loadedContacts = data; 
     System.out.println("AND THE CONTACTS ARE: "); 
     for (Contact c : loadedContacts) { 
      System.out.println("NAME: " + c.getName()); 
      System.out.println("getPhoneNumberHome: " + c.getPhoneNumber()); 
     } 

    } 

    @Override 
    public void onLoaderReset(Loader<ArrayList<Contact>> arg0) { 
     System.out.println("onLoaderReset()"); 
     // TODO Auto-generated method stub 

    } 

} 



package com.example.contactpreload; 

import android.os.Bundle; 
import android.support.v4.app.FragmentActivity; 
import android.view.Menu; 

import com.example.contactpreload.utils.LoadingContacts; 

public class MainActivity extends FragmentActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     LoadingContacts fragment = LoadingContacts.newInstance(1); 
     fragment.setRetainInstance(true); 
     getSupportFragmentManager().beginTransaction() 
      .add(android.R.id.content, fragment).commit(); 
    } 

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

} 

MANIFEST:

<uses-sdk 
    android:minSdkVersion="8" 
    android:targetSdkVersion="16" /> 
+0

@bossylobster, ich habe versucht, auf dieses eine zu antworten, aber ich knacke es nicht. Irgendwelche Eingaben? Was ist mit deinen Kollegen? Was mich erreicht, ist der Level 8 api-Anteil. Es funktioniert tatsächlich mit dem Fragment, aber mit nichts anderem (siehe die folgende Diskussion in der Antwort von wangyif2). –

Antwort

7

AsyncTaskLoader hat nichts mit dem zu tun, ob Sie eine Fragment oder eine Activity verwenden.

Ihnen ein Beispiel geben, eine Liste Aktivität berücksichtigen:

public class ExampleActivity extends ListActivity implements 
LoaderManager.LoaderCallbacks<Cursor> { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.todo_list); 

     //to start the loader: 
     getLoaderManager().initLoader(0, null, this); 
    } 

    //override the loader callback methods as usual 
    // Creates a new loader after the initLoader() call 
    @Override 
    public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
     CursorLoader cursorLoader = new CursorLoader(this, 
     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); 
    } 
} 

Sie Natürlich müssen entsprechende Adapter für die Listenansicht und Layout erstellen, aber das Beispiel, das Sie zeigt, wie eine einfache Lader für Cursor funktionieren würde für eine Aktivität.

Stellen Sie außerdem sicher, dass alle Importe konsistent sind, entweder die support.v4-Bibliothek oder die regelmäßige Bibliothek:

import android.app.LoaderManager; 
import android.content.CursorLoader; 
import android.content.Loader; 

Eine andere Frage, die gestellt wird, ist, dass, wenn der LoaderCallback Schnittstelle Standalone verwendet werden kann. Dies wird nicht empfohlen, wenn Sie bedenken, dass der LoaderCallback für.

The LoaderManager.LoaderCallbacks<D> interface is a simple contract that the LoaderManager uses to report data back to the client. Was das bedeutet, ist seine einzige Aufgabe ist es, einige Daten im Hintergrund von einem Client angefordert, die effektiv ist, eine Aktivität zu laden.

Wenn Sie eine eigenständige Klasse erstellen, können Sie die Klassendefinition erweitern, um LoaderManager.LoaderCallbacks<D> zu implementieren, aber Sie müssen die geladenen Daten über eine Art von Mechanismus an die ursprüngliche Aktivität zurückmelden, was eine einfache Aufgabe verkomplizieren würde.

Nun, wenn du tust, das wirklich fixiert sind, könnten Sie Ihre Standalone-Klasse als so erstellen:

public class LoadingContacts implements LoaderManager.LoaderCallbacks<Cursor> { 
@Override 
public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
    return null; 
} 

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

@Override 
public void onLoaderReset(Loader<Cursor> loader) { 
} 
} 

In Ihrem onLoadFinished Methode, müssen Sie die geladene Cursor zurück, entweder durch eine Sendung schicken, oder eine Art von Nachricht Bus:

  • LocalBroadcastManager
  • Otto
  • Messenger

Nachdem Sie diese Informationen an die MainActivity senden, können Sie es mit dem Adapter laden und weiter gibt.

+1

Vielen Dank für Ihre Antwort: +1. Ich habe jetzt den Code hinzugefügt, der mit Fragment und FragmentActivity funktioniert. Würde es Ihnen etwas ausmachen, es in Ihre Antwort zu schreiben, um zu zeigen, wie es funktionieren würde, wenn 'LoadingContacts' keine übergeordnete Aktivität (z. B. Fragment) hätte und' MainActivity' Fragment FragmentActivity nicht erweitert hätte? – learner

+2

Lassen Sie mich Ihre Frage verstehen, Sie wollen eine 'MainActivity', die' Activity' und 'LoadingContacts' zu einem reinen Loader macht, nicht zu einer' Activity' oder 'Fragment'? – wangyif2

+3

Ich bin neugierig zu sehen, wie das auch funktionieren würde. –