2017-12-11 5 views
1
Aufruf

Bitte empfehlen Sie mir eine Lösung für das Problem:Android, AsyncTask onProgressUpdate und OnPostExecute nicht

Ich bin nicht in der Lage, um herauszufinden, warum onProgressUpdate und OnPostExecute von AsyncTask Klasse wird nicht nach der Ausführung von doInBackground oder OnPreExecute genannt zu werden.

Dies ist meine Fragment-Klasse Rendering Youtube Playlists, wo ich gerne ProgressBar implementieren würde.

public class YouTubeRecyclerViewFragment extends Fragment { 
// the fragment initialization parameter 
private static final String ARG_YOUTUBE_PLAYLIST_IDS = "YOUTUBE_PLAYLIST_IDS"; 
private String[] mPlaylistIds; 
private ArrayList<String> mPlaylistTitles; 
//private RecyclerView mRecyclerView; 
private RecyclerViewPager mRecyclerView; 
private PlaylistVideos mPlaylistVideos; 
private RecyclerView.LayoutManager mLayoutManager; 
private PlaylistCardAdapter mPlaylistCardAdapter; 
private YouTube mYouTubeDataApi; 


public static YouTubeRecyclerViewFragment newInstance(YouTube youTubeDataApi, String[] playlistIds) { 
    YouTubeRecyclerViewFragment fragment = new YouTubeRecyclerViewFragment(); 
    Bundle args = new Bundle(); 
    args.putStringArray(ARG_YOUTUBE_PLAYLIST_IDS, playlistIds); 
    fragment.setArguments(args); 
    fragment.setYouTubeDataApi(youTubeDataApi); 
    return fragment; 
} 

public YouTubeRecyclerViewFragment() { 
    // Required empty public constructor 
} 

public void setYouTubeDataApi(YouTube api) { 
    mYouTubeDataApi = api; 
} 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setRetainInstance(true); 
    if (getArguments() != null) { 
     mPlaylistIds = getArguments().getStringArray(ARG_YOUTUBE_PLAYLIST_IDS); 
    } 

    // start fetching the playlist titles 
    new GetPlaylistTitlesAsyncTask(mYouTubeDataApi) { 
     @Override 
     protected void onPostExecute(PlaylistListResponse playlistListResponse) { 
      // if we didn't receive a response for the playlist titles, then there's nothing to update 
      if (playlistListResponse == null) 
       return; 

      mPlaylistTitles = new ArrayList(); 
      for (com.google.api.services.youtube.model.Playlist playlist : playlistListResponse.getItems()) { 
       mPlaylistTitles.add(playlist.getSnippet().getTitle()); 
      } 
     } 
    }.execute(mPlaylistIds); 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    // set the Picasso debug indicator only for debug builds 
    Picasso.with(getActivity()).setIndicatorsEnabled(BuildConfig.DEBUG); 

    // Inflate the layout for this fragment 
    //View rootView = inflater.inflate(R.layout.youtube_recycler_view_fragment, container, false); 
    View rootView = inflater.inflate(R.layout.youtube_recycler_view_fragment, container, false); 

    //mRecyclerView = (RecyclerView) rootView.findViewById(R.id.youtube_recycler_view); 
    mRecyclerView = (RecyclerViewPager) rootView.findViewById(R.id.youtube_recycler_view); 

    // use this setting to improve performance if you know that changes 
    // in content do not change the layout size of the RecyclerView 
    mRecyclerView.setHasFixedSize(true); 

    Resources resources = getResources(); 
    if (resources.getBoolean(R.bool.isTablet)) { 
     // use a staggered grid layout if we're on a large screen device 
     mLayoutManager = new StaggeredGridLayoutManager(resources.getInteger(R.integer.columns), StaggeredGridLayoutManager.VERTICAL); 
    } else { 
     // use a linear layout on phone devices 
     //mLayoutManager = new LinearLayoutManager(getActivity()); 
     mLayoutManager = new LinearLayoutManager(getActivity(),LinearLayoutManager.VERTICAL,false); 
    } 

    mRecyclerView.setLayoutManager(mLayoutManager); 

    return rootView; 
} 

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

    // if we have a playlist in our retained fragment, use it to populate the UI 
    if (mPlaylistVideos != null) { 
     // reload the UI with the existing playlist. No need to fetch it again 
     reloadUi(mPlaylistVideos, false); 
    } else { 
     // otherwise create an empty playlist using the first item in the playlist id's array 
     mPlaylistVideos = new PlaylistVideos(mPlaylistIds[0]); 
     // and reload the UI with the selected playlist and kick off fetching the playlist content 
     reloadUi(mPlaylistVideos, true); 
    } 
} 

private void reloadUi(final PlaylistVideos playlistVideos, boolean fetchPlaylist) { 
    // initialize the cards adapter 
    initCardAdapter(playlistVideos); 

    if (fetchPlaylist) { 
     // start fetching the selected playlistVideos contents 
     new GetPlaylistAsyncTask(mYouTubeDataApi,getContext()) { 
      @Override 
      public void onPostExecute(Pair<String, List<Video>> result) { 
       handleGetPlaylistResult(playlistVideos, result); 
      } 
     }.execute(playlistVideos.playlistId, playlistVideos.getNextPageToken()); 
    } 
} 

private void initCardAdapter(final PlaylistVideos playlistVideos) { 
    // create the adapter with our playlistVideos and a callback to handle when we reached the last item 
    mPlaylistCardAdapter = new PlaylistCardAdapter(playlistVideos, new LastItemReachedListener() { 
     @Override 
     public void onLastItem(int position, String nextPageToken) { 
      new GetPlaylistAsyncTask(mYouTubeDataApi,getContext()) { 
       @Override 
       public void onPostExecute(Pair<String, List<Video>> result) { 
        handleGetPlaylistResult(playlistVideos, result); 
       } 
      }.execute(playlistVideos.playlistId, playlistVideos.getNextPageToken()); 
     } 
    }); 
    mRecyclerView.setAdapter(mPlaylistCardAdapter); 
} 

private void handleGetPlaylistResult(PlaylistVideos playlistVideos, Pair<String, List<Video>> result) { 
    if (result == null) return; 
    final int positionStart = playlistVideos.size(); 
    playlistVideos.setNextPageToken(result.first); 
    playlistVideos.addAll(result.second); 
    mPlaylistCardAdapter.notifyItemRangeInserted(positionStart, result.second.size()); 
} 

/** 
* Interface used by the {@link PlaylistCardAdapter} to inform us that we reached the last item in the list. 
*/ 
public interface LastItemReachedListener { 
     void onLastItem(int position, String nextPageToken); 
    } 
} 

Unten ist die AsyncTask Klasse, die gelieferten Videos aus der Wiedergabeliste zu holen verwendet wird:

public abstract class GetPlaylistAsyncTask extends AsyncTask<String, Void, Pair<String, List<Video>>> { 
private static final String TAG = "GetPlaylistAsyncTask"; 
private static final Long YOUTUBE_PLAYLIST_MAX_RESULTS = 10L; 

//see: https://developers.google.com/youtube/v3/docs/playlistItems/list 
private static final String YOUTUBE_PLAYLIST_PART = "snippet"; 
private static final String YOUTUBE_PLAYLIST_FIELDS = "pageInfo,nextPageToken,items(id,snippet(resourceId/videoId))"; 
//see: https://developers.google.com/youtube/v3/docs/videos/list 
private static final String YOUTUBE_VIDEOS_PART = "snippet,contentDetails,statistics"; // video resource properties that the response will include. 
private static final String YOUTUBE_VIDEOS_FIELDS = "items(id,snippet(title,description,thumbnails/high),contentDetails/duration,statistics)"; // selector specifying which fields to include in a partial response. 

private YouTube mYouTubeDataApi; 
Context mContext; 
ProgressDialog progressBar; 


public GetPlaylistAsyncTask(YouTube api, Context context) { 
    mYouTubeDataApi = api; 
    mContext = context; 
    progressBar = new ProgressDialog(mContext); 
} 

@Override 
protected Pair<String, List<Video>> doInBackground(String... params) { 
    final String playlistId = params[0]; 
    final String nextPageToken; 

    if (params.length == 2) { 
     nextPageToken = params[1]; 
    } else { 
     nextPageToken = null; 
    } 

    PlaylistItemListResponse playlistItemListResponse; 
    try { 
     playlistItemListResponse = mYouTubeDataApi.playlistItems() 
       .list(YOUTUBE_PLAYLIST_PART) 
       .setPlaylistId(playlistId) 
       .setPageToken(nextPageToken) 
       .setFields(YOUTUBE_PLAYLIST_FIELDS) 
       .setMaxResults(YOUTUBE_PLAYLIST_MAX_RESULTS) 
       .setKey(ApiKey.YOUTUBE_API_KEY) 
       .execute(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     return null; 
    } 

    if (playlistItemListResponse == null) { 
     Log.e(TAG, "Failed to get playlist"); 
     return null; 
    } 

    List<String> videoIds = new ArrayList(); 

    // pull out the video id's from the playlist page 
    for (PlaylistItem item : playlistItemListResponse.getItems()) { 
     videoIds.add(item.getSnippet().getResourceId().getVideoId()); 
    } 

    // get details of the videos on this playlist page 
    VideoListResponse videoListResponse = null; 
    try { 
     videoListResponse = mYouTubeDataApi.videos() 
       .list(YOUTUBE_VIDEOS_PART) 
       .setFields(YOUTUBE_VIDEOS_FIELDS) 
       .setKey(ApiKey.YOUTUBE_API_KEY) 
       .setId(TextUtils.join(",", videoIds)).execute(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    return new Pair(playlistItemListResponse.getNextPageToken(), videoListResponse.getItems()); 
} 

@Override 
protected void onPreExecute() { 
    progressBar = new ProgressDialog(mContext); 
    progressBar.setCancelable(true); 
    progressBar.setMessage("Processing Request"); 
    progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 
    progressBar.setIndeterminate(true); 
    progressBar.show(); 
} 

@Override 
protected void onProgressUpdate(Void... values) { 
    progressBar.setMessage("I have found :"); 
} 

@Override 
protected void onPostExecute(Pair<String, List<Video>> stringListPair) { 
     progressBar.dismiss(); 
    } 
} 
+1

Ist es irgendwo in doInBackground verloren? Hast du den Code debuggt? – ADM

+0

Es zeigt keinen anderen Fehler als die Anzeige von progressBar wird nicht beendet. – Rauhayl

Antwort

1

Sie müssen Listener-Schnittstelle verwenden, verarbeiten hier onPostExecute Funktion wie:

How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?

und ändern Sie das Code-Snippet

new GetPlaylistAsyncTask(mYouTubeDataApi,getContext()) { 
      @Override 
      public void onPostExecute(Pair<String, List<Video>> result) { 
       handleGetPlaylistResult(playlistVideos, result); 
      } 
     }.execute(playlistVideos.playlistId, playlistVideos.getNextPageToken()); 

als

new GetPlaylistAsyncTask(mYouTubeDataApi,getContext(),YouTubeRecyclerViewFragment.this) 
      .execute(playlistVideos.playlistId, playlistVideos.getNextPageToken()); 

    @Override 
    public void handleGetPlaylistResult(PlaylistVideos playlistVideos, Pair<String, List<Video>> result) { 
     if (result == null) return; 
     if (playlistVideos == null){ 
      playlistVideos = mPlaylistVideos; 
     } 
     final int positionStart = playlistVideos.size(); 
     playlistVideos.setNextPageToken(result.first); 
     playlistVideos.addAll(result.second); 
     mPlaylistCardAdapter.notifyItemRangeInserted(positionStart, result.second.size()); 
    } 

GetPlaylistAsyncTask.java

public class GetPlaylistAsyncTask{ 

private AsyncResponse theListener; 

public GetPlaylistAsyncTask(YouTube api, Context context, YouTubeRecyclerViewFragment frag) { 
    mYouTubeDataApi = api; 
    mContext = context; 
    theListener = (AsyncResponse)frag; 
} 

@Override 
     public void onPostExecute(Pair<String, List<Video>> result) { 
      progressBar.dismiss(); 
      theListener.handleGetPlaylistResult(null,result); 
     } 
} 
+0

In der Tat, es ist die Fortschrittsbalken verwerfen, aber das Ergebnis nicht anzeigen. – Rauhayl

+0

Sie müssen Listener verwenden, überprüfen Sie den Link, den ich gesendet habe. Ihre Async-Klasse sollte so aussehen (ich werde meine Antwort aktualisieren) @Rauhayl – mismanc

+0

Vielen Dank @mismanc. Ich freue mich sehr, eine so wertvolle Unterstützung von Ihnen zu erhalten. Ich habe die AsyncResponse-Klasse erstellt und die Methode handleGetPlaylistResult() in YouTubeRecyclerViewFragment implementiert. Die GetPlaylistAsyncTask-Klasse erkennt jedoch nicht den Parameter playlistVideos, der in handleGetPlaylistResult() von der Methode onPostExecute übergeben wird. – Rauhayl

Verwandte Themen