2014-01-13 10 views
0

Кажется, что есть ошибка в библиотеке поддержки v4, я хочу получить доступ к MediaStore Audio с помощью CursorLoader и LoaderManager, и я следил за протоколом к ​​T, и независимо от того, что я делаю, OnLoaderFinished является не называется.onLoadFinished никогда не называется

Вот некоторые фрагменты кода, я создал что-то я назвал MediaStoreInterface,

соответствующие части MediaStoreInterface заключаются в следующем:

public class MediaStoreInterface extends Observable 
{ 
protected Cursor cursor; 
protected static final int LOADER_ID1 = 1; 
protected static final int LOADER_ID2 = 2; 
protected static int lastLoaderId = 0; 
protected static String function = "SONGS"; 
protected static PaudioActivity act; 
protected static Sound selectedSound = null; 
protected static final String[] projections = {MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.DATA}; 
protected static final String[] projectionsPlaylist = {MediaStore.Audio.Playlists._ID,MediaStore.Audio.Playlists.NAME}; 
protected static final Uri sourceUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 
protected static final Uri uriPlaylists = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI; 
protected static ArrayList<String> ret; 
protected static boolean done = false; 
//Singleton 

protected static MediaStoreInterface ref = null; 


public static MediaStoreInterface getMusicLibrary(Activity act_) 
{ 
    if (ref == null) 
     ref = new MediaStoreInterface(act_); 

    return ref;  
} 

protected MediaStoreInterface(Activity act_) 
{ 
    act = (PaudioActivity) act_;   
} 
public static MediaStoreInterface getMSI() 
{ 
    if (android.os.Build.VERSION.SDK_INT < 11) 
     return MediaStoreInterfaceFrodo.getMusicLibrary(act); 
    else 
     return MediaStoreInterfaceHoneyComb.getMusicLibrary(act); 
} 



protected void loadArray(Cursor data) 
{ 
    int num = data.getColumnCount(); 
    if (data == null || !data.moveToFirst()) 
     return; 
    while(!data.isLast()) 
    { 
     String s = data.getString(0); 
     int col = 1; 
     while(col < num) 
      s += "|" + data.getString(col++); 
     ret.add(s); 
     data.moveToNext();   
    } 

    if (function == "SONGS") 
     numSongs = ret.size(); 
    if (function == "PLAYLISTS") 
     numPlaylists = ret.size(); 
    cursor = data; 
} 
public static void setDone() 
{ 
    done = true;  
} 



} 

Это Singleton, который должен вернуть правильный MediaStoreInterface для каждый API, выражаю Фродо из этого, следующим образом:

import java.util.ArrayList; 
import java.util.List; 

import android.app.Activity; 
import android.database.Cursor; 
import android.os.Bundle; 
import android.provider.MediaStore; 
import android.support.v4.app.LoaderManager; 
import android.support.v4.content.CursorLoader; 
import android.support.v4.content.Loader; 
import android.support.v4.content.Loader.OnLoadCompleteListener; 






    public class MediaStoreInterfaceFrodo extends MediaStoreInterface implements LoaderManager.LoaderCallbacks<Cursor>, OnLoadCompleteListener<Cursor> 
    { 

     public static MediaStoreInterface getMusicLibrary(Activity act_) 
     { 
      if (ref == null) 
       ref = new MediaStoreInterfaceFrodo(act_); 

      return ref;  
     } 

     public void setPaudioActivity(PaudioActivity act_) 
     { 
      act = act_; 
     } 

     protected MediaStoreInterfaceFrodo(Activity act_) 
     { 
      super(act_); 
     } 

     public ArrayList<String> getSongList() 
     { 
      function = "SONGS"; 
      done = false; 
      if (ret == null) 
       ret = new ArrayList<String>(); 
      else 
       ret.clear(); 
      lastLoaderId = LOADER_ID1; 
      LoaderManager lm = act.getSupportLoaderManager(); 
      Loader<Cursor> loader1 = lm.getLoader(LOADER_ID1); 
      if (loader1 != null && loader1.isReset()) 
       loader1 = lm.restartLoader(LOADER_ID1, null, this); 
      else 
      { 
       loader1 = lm.initLoader(LOADER_ID1, null, this);  
      } 

      while(!done) 
      { 
       waitabit(); 
      } 

      return ret; 
     } 

     public static void editSelectedSongTitle(String newtitle) 
     { 
      // TODO Auto-generated method stub  
     } 



     public static void setContinuePlayMode(PlayMode pm_) 
     { 
      pm = pm_;  
     } 

     public List<String> getPlayListNames() 
     { 
      function = "PLAYLISTS"; 
      done = false; 
      if (ret == null) 
       ret = new ArrayList<String>(); 
      else 
       ret.clear(); 
      lastLoaderId = LOADER_ID2; 
      LoaderManager lm = act.getSupportLoaderManager(); 
      lm.initLoader(LOADER_ID2, null, this); 

      while(!done) 
      { 
       waitabit(); 
      } 

      function = "SONGS"; 

      return ret; 

     } 





     @Override 
     public Loader<Cursor> onCreateLoader(int id, Bundle arg1) 
     { 
      CursorLoader cursorLoader = null; 

      switch (id) 
      { 
      case LOADER_ID1: 
       cursorLoader = new CursorLoader(act, sourceUri, projections, null, null, MediaStore.Audio.Media.TITLE); 
       break; 
      case LOADER_ID2: 
       cursorLoader = new CursorLoader(act, uriPlaylists, projectionsPlaylist, null, null, MediaStore.Audio.Playlists.NAME); 
       break; 
      default: 
       break; 
      } 
      cursorLoader.forceLoad(); 
      return cursorLoader; 

     } 

     @Override 
     public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor data) 
     { 
      cursor = data; 
      loadArray(cursor); 
      done = true; 

     } 

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

      act.getSupportLoaderManager().restartLoader(lastLoaderId, null, (android.support.v4.app.LoaderManager.LoaderCallbacks<Cursor>) this); 

     } 

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

     } 




    } 

Я попытался отделить DAT сбавьте запрос от обычных ядер и судорог моей деятельности. Короче говоря, у меня есть кнопка, которая, если один щелчок, вызывается getSongList, У меня также есть setActivity, чтобы включить участника действия в вызывающую активность,

Я читал ВСЕ соответствующие статьи StackOverflow и все на сайте разработки Android. Некоторые из вас могут возразить, что мне нужно вызвать некоторые из моих функций в потоке пользовательского интерфейса, я тоже это сделал, но безрезультатно. В моей основной деятельности я реализовал один и тот же набор кода, но все равно неважно, что я делаю. OnLoadFinished никогда не вызывается.

+0

Вы уверены, что ваш initLoader был вызван? пожалуйста, следуйте инструкциям https://github.com/emil10001/AndroidSerialSQL/tree/sample и https://github.com/emil10001/AndroidSerialSQL –

+0

. Я перешагиваю свой код и, перейдя через initLoader, вижу, что onCreateLoader, я также добавил источник и сделал шаг, который снова подтвердил, что вызывается initLoader. благодарю вас за ваш комментарий, хотя, я очень его ценю, и я собираюсь прочитать материал на тех ссылках, которые вы предоставили сразу. – dariusiv

+0

да sue..hope вы сможете решить это с помощью этих ссылок и стилей написания кода –

ответ

3

Я не уверен, что вызывает проблемы, так как ваш код является неполным, однако ваши импорта предполагают, что вы не могли бы использовать активность из пакета поддержки:

импорта android.app.Activity;

должен быть

импорт android.support.v4.app.FragmentActivity;

я на самом деле не вижу, как ваш код может даже составить, так как без поддержки, деятельность не имеет метод, называемый getSupportLoaderManager()

, не зная, что фактическая проблема, я» Я выложу образец, который я только что создал, я сварил код до того, что на самом деле необходимо. Обратите внимание, однако, что вам не нужно реализовывать LoaderCallback в активности.Этот код работает, как я его протестировал.

package com.suhw.samples.mediastore; 

import android.database.Cursor; 
import android.net.Uri; 
import android.os.Bundle; 
import android.provider.MediaStore; 
import android.support.v4.app.FragmentActivity; 
import android.support.v4.app.LoaderManager; 
import android.support.v4.content.CursorLoader; 
import android.support.v4.content.Loader; 
import android.util.Log; 

public class QueryMediaStoreActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor> { 
    private final static String TAG = "QueryMediaStoreActivity"; 
    private static final int LOADER_ID1 = 1; 
    private static final String[] audioMediaProjection = {MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.DATA}; 
    private static final Uri audioMediaUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     LoaderManager loaderManager = getSupportLoaderManager(); 
     loaderManager.initLoader(LOADER_ID1, null, this); 
    } 


    @Override 
    public Loader<Cursor> onCreateLoader(int id, Bundle bundle) { 
     switch (id) { 
      case LOADER_ID1: 
       return new CursorLoader(this, audioMediaUri, audioMediaProjection, null, null, MediaStore.Audio.Media.TITLE); 
      default: 
       return null; 
     } 
    } 

    @Override 
    public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) { 
     switch (cursorLoader.getId()) { 
      case LOADER_ID1: 
       Log.d(TAG, "onLoadFinished called:\n\tcursorCount:" + cursor.getCount()); 
       break; 
     } 
    } 

    @Override 
    public void onLoaderReset(Loader<Cursor> cursorLoader) { 
    } 
} 
+0

большое спасибо. поэтому вы можете вызвать getSupportLoaderManager из FragmentActivity?Моя основная деятельность была расширена из ActionBarActivity, которая сама является расширением FragmentActivity, но я не был вызван getSupportLoaderManager в потоке пользовательского интерфейса FragmentActivity, я установил это в MediaStoreInterface, у которого было действие Activity, называемое act, как это MainActivity акт; , и я бы поставил экземпляр моего ActionBarActivity там, как тогда, когда мне нужен список песен, я бы назвал getSupportLoaderManager оттуда, с act.getSupportLoaderManager – dariusiv

+0

Да, getSupportLoaderManager() можно вызывать только из FragmentActivity. В случае с не-поддержкой-библиотекой вы просто вызываете getLoaderManager(). –

1

Измените свой OncreateLoader(), Если вы имеете дело с несколькими загрузчиками, тогда лучше используйте инструкцию switch().

@Override 
    public Loader<Cursor> onCreateLoader(int id, Bundle arg1) 
    { 
     CursorLoader cursorLoader = null; 

     switch (id) { 
     case LOADER_ID1: 
      cursorLoader = new CursorLoader(getActivity(), sourceUri, projections, null, null, MediaStore.Audio.Media.TITLE); 
      break; 
     case LOADER_ID2: 
      cursorLoader = new CursorLoader(getActivity(), uriPlaylists, projectionsPlaylist, null, null, MediaStore.Audio.Playlists.NAME); 
      break; 
     default: 
      break; 
     } 
     cursorLoader.forceLoad(); 
     return cursorLoader; 

    } 

Edit: -

Использование getActivity() вместо act для деталей CursorLoader

Примечание: - Метод getLoaderManager() доступен только в классе фрагмента. Чтобы получить LoaderManager в FragmentActivity, вызовите getSupportLoaderManager().

Попробуйте вот так.

+0

спасибо Amit, я тоже это сделал, в предыдущей версии я использовал этот плейлист второго типа, я бы, вероятно, никогда не использовал его, но вы видите, что это не проблема, проблема в том, что после выполнения каждой книги загрузка никогда не завершается, а onLoadFinished никогда не вызывается. – dariusiv

+0

, как вы можете видеть выше, мой MediaStoreInterface не является расширением Activity или Fragment или FragmentActivity, возможно, это должно быть, но это не так. Я использую getSupportLoaderManager, где-то выше, у меня есть что-то вроде setActivity (Activity act_) { акт = act_ } и вот как MediaStoreInterface знает, кто назвал деятельность и родительский контекст, вы думаете, что это проблема? Я пытался отделить логику запроса и курсора и все это от пользовательского интерфейса и активности, но иногда и спецификаций потоков пользовательского интерфейса Android, затрудняет это. – dariusiv

+0

Теперь я понимаю, что вы говорите. Я могу получить только допустимый LoaderManager, если я вызову getSupportLoaderManager в потоке пользовательского интерфейса функции FragmentActivity в методе onCreate. правильно? – dariusiv

Смежные вопросы