我非常非常因为我在等待网络通话时尝试实施超级简单的加载轮而感到沮丧。我搜索并阅读了几十个SO问题,我觉得我必须遗漏一些东西,除非没有人真正做我想做的事情。我尝试过AsyncTask
路线,但这不是我想要的。
我还要说现在我的应用程序运行正常,只是屏幕上的转换似乎在网络上等待时挂起。我只想要一个加载轮,以便在1-2秒内用户知道应用程序正在运行并且没有冻结。
以下是我当前的网络电话:
private static String sendDataToServer(String arg1, String arg2)
{
Thread dbThread = new Thread()
{
public void run()
{
// do the call that takes a long time
}
};
dbThread.start();
try {
// I do this so that my program doesn't continue until
// the network call is done and I have received the information
// I need to render my next screen
dbThread.join();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
现在,为什么我不能像这样添加ProgressDialog
?如果我这样做,progressDialog永远不会出现。
private static String sendDataToServer(String arg1, String arg2)
{
final ProgressDialog progress = new ProgressDialog(BaseActivity.getInstance());
progress.setIndeterminate(true);
progress.setMessage("Loading...");
progress.show();
Thread dbThread = new Thread()
{
public void run()
{
// do the call that takes a long time
}
};
dbThread.start();
try {
dbThread.join();
progress.dismiss();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
我认为我被卡住了,因为网络调用需要与UI线程位于一个单独的线程上,但我不想继续使用我的应用程序,因为我需要继续执行该调用的结果。但如果我做thread.join()
我就会把所有东西都拿走。我以为我需要AsyncTask
,但那很快就会走下坡路。如果你很好奇,这是我的问题。
Android's AsyncTask: multiple params, returning values, waiting
如果这个调用发生时我只是显示一个加载对话框而没有继续我的其余应用程序,那该怎么办?
修改
这是我的AsyncTask
尝试。
private class PostToFile extends AsyncTask<PostToFile, Void, Void>{
private String functionName;
private ArrayList<NameValuePair> postKeyValuePairs;
private String result = "";
public PostToFile(String function, ArrayList<NameValuePair> keyValuePairs){
functionName= function;
postKeyValuePairs = keyValuePairs;
}
@Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(BaseActivity.getInstance(), "Loading", "Please wait...", true, false);
}
@Override
protected Void doInBackground(PostToFile... params) {
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair(FUNCTION_KEYWORD, functionName));
for (int i = 0; i < postKeyValuePairs.size(); i++) {
nameValuePairs.add(postKeyValuePairs.get(i));
}
try{
// ***do the POST magic.***
result = response.toString();
}
catch (Exception e){
// clean up my mess
}
return null;
}
private String getResult(){
return result; // can I use this somehow???
}
@Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
}
}
当我使用它时:
new PostToPHP(FUNCTION_NAME, postPairings){
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
try
{
if (result != null && !result.startsWith("null"))
{
JSONArray jArray = new JSONArray(result);
parseData(jArray);
}
}
catch (JSONException e)
{
Log.e(Constants.LOG_TAG, e.toString());
}
};
}.execute()
问题是,我有几个这样的呼叫背靠背,并且它们各自依赖于彼此。所以第一个开始,第二个开始立即在第一个开始后,但之前第一个完成。所以我得到了错误的行为。如何在完成第一个电话完成后才能开始第二个电话?
答案 0 :(得分:2)
也许这会起作用,我还没有测试过,但你可以尝试:
public class MyTask extends AsyncTask<String, Void, String> {
private int flag;
public MyTask(int flag) {
this.flag = flag;
}
@Override
protected String doInBackground(String... params) {
switch (flag) {
case 1:
return doNetworking1();
break;
case 2:
return doNetworking2();
break;
case 3:
return doNetworking3();
break;
default:
return doNetworking1();
}
}
@Override
protected void onPreExecute() {
//show progress dialog
}
@Override
protected void onPostExecute(String s) {
//hide progress dialog
switch (flag) {
case 1: //do something with result
new MyTask(2).execute();
break;
case 2: //do other stuff
new MyTask(3).execute();
break;
case 3: //do event more stuff
break;
default:
//do something
}
}
}
和用法:
new MyTask(1).execute();
答案 1 :(得分:1)
如果是网络连接,我会使用IntentService
代替AsyncTask
。
例如,为网络连接创建IntentServices:
public class NetworkCallIntentService extends IntentService {
public static final String BROADCAST_ACTION = "com.yourpackage:NETWORK_CALL_BROADCAST";
public static final String RESULT = "com.yourpackage:NETWORK_CALL_RESULT";
public NetworkCallIntentService() {
super(NetworkCallIntentService.class.getSimpleName());
}
@Override
protected void onHandleIntent(Intent intent) {
// get data from intent if needed
// do the call that takes long time
// send broadcast when done
Intent intent = new Intent(BROADCAST_ACTION);
intent.putExtra(RESULT, "some_result");//and more results
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
接下来,从活动启动该服务,显示进度对话框并将负责显示下一个屏幕的代码移动到BroadcastReceiver#onReceive()
方法:
public class SomeActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//start service
Intent serviceIntent = new Intent(this, NetworkCallIntentService.class);
//put extras into intent if needed
//serviceIntent.putExtra("some_key", "some_string_value");
startService(serviceIntent);
//here just show progress bar/progress dialog
}
@Override
protected void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(mNetworkCallReceiver,
new IntentFilter(NetworkCallIntentService.BROADCAST_ACTION));
}
@Override
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(mNetworkCallReceiver);
}
private BroadcastReceiver mNetworkCallReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//hide progress bar/progress dialog
//here get results from intent extras
String result = intent.getStringExtra(NetworkCallIntentService.RESULT);
//process results and continue program(go to next screen, show error message etc.)
}
}
}
在清单文件中声明服务:
<service
android:name="com.yourpackage.DownloadSvtValuesIntentService"
android:exported="false" >
</service>