我实现了代码以使用异步任务并且它工作得很好,但是如果用户退出应用程序它会很快被杀死,所以我决定尝试使用服务,它运行完美,但它会使应用程序冻结
所以这是我的解压缩课程:
public class Decompress {
private String _zipFile;
private String _location;
ZipEntry ze = null;
public Decompress(String zipFile, String location) {
_zipFile = zipFile;
_location = location;
_dirChecker("");
}
public void unzip() {
try {
FileInputStream fin = new FileInputStream(_zipFile);
ZipInputStream zin = new ZipInputStream(fin);
while ((ze = zin.getNextEntry()) != null) {
//Log.v("Decompress", "Unzipping " + ze.getName());
if(ze.isDirectory()) {
_dirChecker(ze.getName());
} else {
FileOutputStream fout = new FileOutputStream(_location + ze.getName());
for (int c = zin.read(); c != -1; c = zin.read()) {
fout.write(c);
}
zin.closeEntry();
fout.close();
}
}
zin.close();
} catch(Exception e) {
Log.e("Decompress", "unzip", e);
}
}
private void _dirChecker(String dir) {
File f = new File(_location + dir);
if(!f.isDirectory()) {
f.mkdirs();
}
}
}
这是我的服务调用解压缩:
@Override
public void onStart(Intent intent, int startid)
{
try
{
zipFile = intent.getStringExtra("zipFile");
zipLocation = intent.getStringExtra("unzipLocation");
String fileS = intent.getStringExtra("file");
file = new File(fileS);
fin = new FileInputStream(zipFile);
zin = new ZipInputStream(fin);
while (zin.getNextEntry() != null) {
numFiles++;
}
}
catch (FileNotFoundException e)
{}
catch (IOException e)
{}
d = new Decompress(zipFile, zipLocation);
d.unzip();
}
现在我在这里使用异步任务来调用它:
@Override
protected Void doInBackground(Void... params) {
d.unzip();
return null;
}
现在我的问题是,为什么使用异步tsk我的应用程序不会被冻结并且它将保持解压缩让我用按钮取消它,但是使用服务它会使应用程序滞后?我甚至收到一条关于MyApp没有响应的消息,你想关闭吗?
编辑:我的服务电话是开始
@Override
protected Void doInBackground(Void... params) {
Intent intent = new Intent(DownloadFiles.this, MyService.class);
String unzipLocation = Environment.getExternalStorageDirectory().toString()+"/Android/data/";
String zipFile = Environment.getExternalStorageDirectory().toString()+"/Android/data/test.zip";
intent.putExtra("zipFile", zipFile);
intent.putExtra("unzipLocation", unzipLocation);
intent.putExtra("file", Environment.getExternalStorageDirectory().toString()+"/Android/data/");
startService(intent);
try {
FileInputStream fin = new FileInputStream(zipFile);
ZipInputStream zin = new ZipInputStream(fin);
while (zin.getNextEntry() != null) {
numFiles++;
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
答案 0 :(得分:3)
服务也在UI(主)线程中运行,因此您还需要在那里实现AsyncTask或sepearate Thread方法。
docs在什么是服务?
下说出这一切服务不是线程。它本身不是从主线程开始工作的手段(以避免应用程序无响应错误)。
编辑:请注意,如果从后台线程启动服务,该服务仍在主线程中运行。根据这个SO answer。这应该是正确的,因为文档说:
实际创建服务组件时,对于其中任何一个 原因,系统实际做的就是实例化 组件并调用其onCreate()和任何其他适当的回调 在主线程上。由服务部门来实现这些 适当的行为,例如创建其中的辅助线程 它做了它的工作。
这最终意味着无论您如何启动服务,都应该始终在Services中实现单独的AsyncTask / Thread方法。
答案 1 :(得分:1)
如果您不需要AsyncTask的onPreExecute()
和onPostExecute()
方法,请尝试在单独的后台线程中运行它,但仍然存在阻止UI线程的操作的问题。
Thread t = new Thread() {
public void run() {
d = new Decompress(zipFile, zipLocation);
d.unzip();
}
};
t.start();
简单地从后台线程启动服务并不意味着它将从主UI线程启动。这是它的开始默认值,您必须在服务中创建一个新线程来绕过它。
答案 2 :(得分:1)
扩大A - C的观点: 您需要创建后台线程以从服务中的解压缩文件,因为该服务已创建并在主线程上运行,无论您是否在另一个线程内启动它。
您基本上需要在服务中完成您在服务之外所做的事情(即将'unzip'调用放在AsyncTask中,并执行任务)。
(附录) 使用服务的关键不是创建单独的线程,而是从基于UI的应用程序中拆分耗时的处理。这意味着操作系统可以销毁UI并恢复资源,并且服务仍然在运行。 因此,关于是否在应用程序本身与服务中使用AsyncTask(或线程)的决定实际上是关于该动作是否应该独立于应用程序界面而继续。使用TitaniumBackup恢复应用程序就是一个很好的例子:一旦你开始恢复,就不再需要应用程序UI了。