我正在尝试编写一个更新的简单应用程序.为此,我需要一个简单的功能,可以下载一个文件,并显示当前进度的ProgressDialog
.我知道怎么做ProgressDialog
,但我不知道如何显示当前进度以及如何首先下载文件.
我正在阅读AsyncTask
,我尝试了下面的简单程序.但它似乎没有用.我怎样才能使它工作?
public class AsyncTaskActivity extends Activity {
Button btn;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener((OnClickListener) this);
}
public void onClick(View view){
new LongOperation().execute("");
}
private class LongOperation extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
for(int i=0;i<5;i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
TextView txt = (TextView) findViewById(R.id.output); …
Run Code Online (Sandbox Code Playgroud) 从在UI线程中运行代码的角度来看,之间有什么区别:
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
Run Code Online (Sandbox Code Playgroud)
要么
MainActivity.this.myView.post(new Runnable() {
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
Run Code Online (Sandbox Code Playgroud)
和
private class BackgroundTask extends AsyncTask<String, Void, Bitmap> {
protected void onPostExecute(Bitmap result) {
Log.d("UI thread", "I am the UI thread");
}
}
Run Code Online (Sandbox Code Playgroud) 我有一个可以拉起来的滑块,然后它会显示一张地图.我可以上下移动滑块来隐藏或显示地图.当地图在前面时,我可以处理该地图上的触摸事件.每当我触摸时,a AsyncTask
会被启动,它会下载一些数据并生成一个Toast
显示数据的数据.虽然我在触摸事件上启动任务但是没有显示吐司,直到我关闭滑块.当滑块关闭并且不再显示地图时,会Toast
出现.
有任何想法吗?
好了开始任务
编辑:
public boolean onTouchEvent(MotionEvent event, MapView mapView){
if (event.getAction() == 1) {
new TestTask(this).execute();
return true;
}else{
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
并onPostExecute
祝酒
Toast.makeText(app.getBaseContext(),(String)data.result,
Toast.LENGTH_SHORT).show();
Run Code Online (Sandbox Code Playgroud)
在新的TestTask(this)
,这是一个参考,MapOverlay
而不是MapActivity
,所以这是问题.
我稍微感到困惑之间的差异Handlers
,AsyncTask
并Threads
在Android中.我在stackoverflow中阅读了很多博客和问题.
Handler
是后台线程,提供您与UI进行通信.例如,更新进度条应该通过Handler
.使用处理程序可以获得优势MessagingQueues
,因此,如果要计划消息或更新多个UI元素或具有重复任务.
AsyncTask
类似的,实际上它们使用Handler
但不在UI线程中运行,因此它对于获取数据很有用,例如获取Web服务.稍后您可以与UI进行交互.
Thread
然而,无法与UI交互,提供更多"基本"线程,你错过了所有的抽象AsyncTask
.
但是,我想在服务中运行套接字连接.应该在处理程序或线程中运行,还是在AsyncTask
?根本不需要UI交互.它在我使用的性能方面有所不同吗?
与此同时,文件已得到重大改进.
我有这两节课.我的主要活动和扩展的一个AsyncTask
,现在在我的主要活动,我需要从得到的结果OnPostExecute()
中AsyncTask
.我怎样才能将结果传递给我的主要活动?
这是示例代码.
我的主要活动.
public class MainActivity extends Activity{
AasyncTask asyncTask = new AasyncTask();
@Override
public void onCreate(Bundle aBundle) {
super.onCreate(aBundle);
//Calling the AsyncTask class to start to execute.
asyncTask.execute(a.targetServer);
//Creating a TextView.
TextView displayUI = asyncTask.dataDisplay;
displayUI = new TextView(this);
this.setContentView(tTextView);
}
}
Run Code Online (Sandbox Code Playgroud)
这是AsyncTask类
public class AasyncTask extends AsyncTask<String, Void, String> {
TextView dataDisplay; //store the data
String soapAction = "http://sample.com"; //SOAPAction header line.
String targetServer = "https://sampletargeturl.com"; //Target Server.
//SOAP Request.
String soapRequest …
Run Code Online (Sandbox Code Playgroud) 我已经调查了这个问题好几个月了,想出了不同的解决方案,我不满意,因为它们都是大规模的黑客攻击.我仍然无法相信一个设计有缺陷的课程已经进入框架而没有人在讨论它,所以我想我一定要错过一些东西.
问题在于AsyncTask
.根据它的文件
"允许执行后台操作并在UI线程上发布结果,而无需操纵线程和/或处理程序."
然后该示例继续示出如何showDialog()
调用一些示例性方法onPostExecute()
.然而,这对我来说似乎完全是设计的,因为显示一个对话框总是需要引用一个有效的Context
,而AsyncTask 绝不能保持对上下文对象的强引用.
原因很明显:如果活动被破坏而触发任务怎么办?这可能一直发生,例如因为你翻转了屏幕.如果任务将持有对创建它的上下文的引用,那么您不仅要继续使用无用的上下文对象(窗口将被销毁,并且任何 UI交互都会因异常而失败!),您甚至可能会创建一个内存泄漏.
除非我的逻辑在这里有缺陷,否则转换为:onPostExecute()
完全没用,因为如果你没有访问任何上下文,这个方法在UI线程上运行有什么用?你不能在这里做任何有意义的事情.
一种解决方法是不将上下文实例传递给AsyncTask,而是传递给Handler
实例.这是有效的:因为Handler松散地绑定了上下文和任务,所以你可以在它们之间交换消息而不会有泄漏的风险(对吧?).但这意味着AsyncTask的前提,即您不需要打扰处理程序,是错误的.它似乎也滥用了Handler,因为你在同一个线程上发送和接收消息(你在UI线程上创建它并在onPostExecute()中通过它发送它也在UI线程上执行).
最重要的是,即使使用了这种解决方法,您仍然会遇到这样的问题:当上下文被破坏时,您没有记录它触发的任务.这意味着您必须在重新创建上下文时重新启动任何任务,例如在屏幕方向更改后.这是缓慢而浪费的.
我对此的解决方案(在Droid-Fu库中实现)是维护WeakReference
s从组件名称到其唯一应用程序对象上的当前实例的映射.每当启动AsyncTask时,它都会在该映射中记录调用上下文,并且在每次回调时,它将从该映射中获取当前上下文实例.这可以确保您永远不会引用陈旧的上下文实例,并且您始终可以访问回调中的有效上下文,这样您就可以在那里进行有意义的UI工作.它也不会泄漏,因为引用很弱并且在没有给定组件的实例存在时被清除.
尽管如此,这是一个复杂的解决方法,需要对一些Droid-Fu库类进行子类化,这使得这种方法非常具有侵入性.
现在我只想知道:我是否只是大量遗漏某些东西,或者AsyncTask是否真的完全有缺陷?您的使用经验如何?你是怎么解决这些问题的?
感谢您的输入.
我正在尝试同时运行两个AsyncTasks.(平台是Android 1.5,HTC Hero.)但是,只有第一个被执行.这是一个描述我的问题的简单片段:
public class AndroidJunk extends Activity {
class PrinterTask extends AsyncTask<String, Void, Void> {
protected Void doInBackground(String ... x) {
while (true) {
System.out.println(x[0]);
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new PrinterTask().execute("bar bar bar");
new PrinterTask().execute("foo foo foo");
System.out.println("onCreate() is done.");
}
}
Run Code Online (Sandbox Code Playgroud)
我期望的输出是:
onCreate() is done.
bar bar bar
foo foo foo
bar bar bar
foo foo foo
Run Code Online (Sandbox Code Playgroud)
等等.但是,我得到的是:
onCreate() is done. …
Run Code Online (Sandbox Code Playgroud) 我在我的代码中收到警告:
这个AsyncTask类应该是静态的,否则可能会发生泄漏(匿名android.os.AsyncTask)
完整的警告是:
此AsyncTask类应该是静态的,否则可能会发生泄漏(匿名android.os.AsyncTask)静态字段将泄漏上下文.非静态内部类具有对其外部类的隐式引用.如果该外部类例如是片段或活动,则此引用意味着长时间运行的处理程序/加载器/任务将保留对活动的引用,从而阻止其收集垃圾.同样,对来自这些较长时间运行的实例的活动和片段的直接字段引用可能会导致泄漏.ViewModel类绝不应指向视图或非应用程序上下文.
这是我的代码:
new AsyncTask<Void,Void,Void>(){
@Override
protected Void doInBackground(Void... params) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.notifyDataSetChanged();
}
});
return null;
}
}.execute();
Run Code Online (Sandbox Code Playgroud)
我该如何纠正?
我目前正在我的应用程序中使用listview,可能需要一秒钟才能显示.
我目前所做的是使用listview的@ id/android:empty属性来创建"加载"文本.
<TextView android:id="@id/android:empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF0000"
android:text="Loading..."/>
Run Code Online (Sandbox Code Playgroud)
现在,我想用加载对话框中使用的动画圆代替此文本,我想你们都知道我的意思:
编辑:我不想要对话.我想在我的布局中展示它.
非常感谢您的帮助!
android ×10
android-ui ×1
android-view ×1
concurrency ×1
download ×1
geometry ×1
handler ×1
java ×1
loading ×1
toast ×1