目前,我的AsyncTask
内有一个RecyclerView.Adapter
被调用,其中我正在从网址下载文件并且我的ViewHolder
内部正在显示进度我的AsyncTask
看起来:
public class DownloadFileFromURL extends AsyncTask<String, String, String> {
int positionnumber;
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(String... f_url) {
int count;
String pathreference = f_url[0] + ",";
positionnumber = Integer.parseInt(f_url[0]);
isDownloading.set(positionnumber, true);
try {
URL url = new URL(f_url[1]);
URLConnection conection = url.openConnection();
conection.connect();
// this will be useful so that you can show a tipical 0-100%
// progress bar
int lenghtOfFile = conection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url.openStream(),
8192);
if (isCancelled()) {
return null;
}
if (a.equals("one")) {
// Output stream
OutputStream output = new FileOutputStream(Environment
.getExternalStorageDirectory().toString()
+ "/" + setDownloadedName + ".mp4");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
// After this onProgressUpdate will be called
if (isCancelled()) {
input.close();
return null;
}
publishProgress("" + (int) ((total * 100) / lenghtOfFile));
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
pathreference = pathreference + Environment.getExternalStorageDirectory().toString() + "/" + setDownloadedName + ".mp4";
// closing streams
output.close();
input.close();
}
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return pathreference;
}
protected void onProgressUpdate(String... progress) {
prog = progress[0];
Log.d("Progress", progress[0]);
bars.get(positionnumber).setProgress_(Float.parseFloat(progress[0]));
float p = bars.get(positionnumber).getProgress_();
if (p % 1 == 0)
notifyItemChanged(positionnumber);
}
@Override
protected void onPostExecute(String file_url) {
String[] split = file_url.split(",");
int index1 = Integer.parseInt(split[0]);
try {
videoHolderClass.get(index1).setImage(imgres[0]);
bars.get(index1).setProgress_(0);
manager.insertVideoPath(index1 + "", split[1]);
RecyclerVideoAdapter.this.notifyItemChanged(index1);
isDownloading.set(index1, false);
Log.d("done", "filesaved");
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
Toast.makeText(c, "Network Error..", Toast.LENGTH_SHORT).show();
prog = "";
networkFailed = "yes";
videoHolderClass.get(index1).setImage(imgres[1]);
bars.get(index1).setProgress_(0);
RecyclerVideoAdapter.this.notifyItemChanged(index1);
isDownloading.set(index1, false);
}
}
}
RecyclerView
位于片段内,片段填充在Activity
- ViewPager
中。
现在,每当我关闭活动或转到新活动并返回时,都不会再显示进度。
我见过人们会做以下事情:
if(mtask.getStatus() == AsyncTask.Status.FINISHED){
// My AsyncTask is done and onPostExecute was called
}
但问题是AsyncTask
在Adapter
中,所以我无法在我的片段中引用它。
我的问题:
有人可以向我解释一下,查看AsyncTask
是否正在运行的正确方法是什么,并在重新创建活动时更新进度?
答案 0 :(得分:0)
我知道这不是&#34;正确&#34;这样做的方式 ,但我已经设法找到了解决办法,它适用于我想要实现的目标。
我决定使用SharedPreferences
检查文件是否正在下载。在我的onPreExecute
中,我执行了以下操作:
@Override
protected void onPreExecute() {
super.onPreExecute();
SharedPreferences sharePrefss = c.getSharedPreferences("busyDownloading", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharePrefss.edit();
editor.putString("isItBusy", "yes");
editor.apply();
}
上面我存储了一个String
名为&#34; isItBusy&#34;我把它设置为是。
然后在onPostExecute
我将SharedPreferences
更改为:
SharedPreferences sharePrefss = c.getSharedPreferences("busyDownloading", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharePrefss.edit();
editor.putString("isItBusy", "no");
editor.apply();
在我的Activity
中,当用户按下后退按钮时,我会执行以下操作:
@Override
public void onBackPressed() {
SharedPreferences sharePrefs = getSharedPreferences("busyDownloading", Context.MODE_PRIVATE);
String getSharedUser = sharePrefs.getString("isItBusy", "");
if (getSharedUser.equals("yes")){
// AsyncTask - onPostExecute was not called = moveTaskToBack
moveTaskToBack(true);
}else {
//AsyncTask - onPostExecute was called and application can be destroyed
finish();
}
}
通过以上操作,我现在知道文件是否仍在忙于下载并相应地处理后退按钮。
下一个问题是处理设备的旋转,因为当设备旋转时,Activity
会被销毁并再次创建。
要解决这个问题,我做的第一件事就是通过将setRetainInstance(true);
添加到我的片段onCreateView
来保留片段状态。然后在我的清单中,我将android:configChanges="orientation|screenSize"
添加到我的Activity
。
这样做解决了轮换问题。
@vsatkh提到的最后一个问题是对下载进行排队。我下载的文件不是那么大(最多约2-5MB)。所以我决定一次只启用一次下载,同时检查SharedPreferences
,如下所示:
holder.setItemClickListener(new ItemClickListener() {
@Override
public void onItemClick(View v, int pos) {
SharedPreferences sharePrefs = c.getSharedPreferences("busyDownloading", Context.MODE_PRIVATE);
String getSharedUser = sharePrefs.getString("isItBusy", "");
if (getSharedUser.equals("yes")){
Toast.makeText(c, "You can only download one file at a time...", Toast.LENGTH_SHORT).show();
}else {
DownloadFileFromURL p = new DownloadFileFromURL();
p.execute(pos + "", downloadLink);
}
}
});
上面不包括我使用的所有方法(比如检查文件是否已存在),只包括与我问的问题相关的方法。