Android,AsyncTask 不调用 onProgressUpdate 和 onPostExecute
Posted
技术标签:
【中文标题】Android,AsyncTask 不调用 onProgressUpdate 和 onPostExecute【英文标题】:Android, AsyncTask not calling onProgressUpdate and onPostExecute 【发布时间】:2018-05-24 15:12:46 【问题描述】:请建议我解决此问题:
我无法弄清楚为什么在执行 doInBackground 或 onPreExecute 后没有调用 AsyncTask 类的 onProgressUpdate 和 onPostExecute。
这是我的 Fragment 类渲染 Youtube 播放列表,我想在其中实现 ProgressBar。
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);
下面是用于从提供的播放列表中获取视频的 AsyncTask 类:
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();
【问题讨论】:
它是否丢失在 doInBackground 某处?你调试过代码吗? 除了显示progressBar没有被终止之外,它没有显示任何错误。 【参考方案1】:你需要使用监听接口,像这里处理onPostExecute
函数:
How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?
并更改代码sn-p
new GetPlaylistAsyncTask(mYouTubeDataApi,getContext())
@Override
public void onPostExecute(Pair<String, List<Video>> result)
handleGetPlaylistResult(playlistVideos, result);
.execute(playlistVideos.playlistId, playlistVideos.getNextPageToken());
作为
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);
【讨论】:
确实,它正在关闭progressBar但不显示结果。 您需要使用监听器检查我发送的链接。你的 Async 类应该是这样的(我会更新我的答案)@Rauhayl 谢谢@mismanc。我非常高兴能得到您如此宝贵的支持。我在 YouTubeRecyclerViewFragment 中创建了 AsyncResponse 类并实现了 handleGetPlaylistResult() 方法。但是GetPlaylistAsyncTask类不能识别从onPostExecute方法传入handleGetPlaylistResult()的playlistVideos参数。 你不需要发送playlistVideos
参数。在您的片段中,您已经拥有它。
请查看以下课程以获得清晰的视图。 AsyncResponse 类link、GetPlaylistAsyncTask 类link 和YouTubeRecyclerViewFragment 类link以上是关于Android,AsyncTask 不调用 onProgressUpdate 和 onPostExecute的主要内容,如果未能解决你的问题,请参考以下文章
没有 SD 卡时,ProgressDialog 不显示在 Galaxy S3 上
在上下文不工作的情况下从 AsyncTask onPostExecute 调用 Android Intent