開始;是的,我到處都在尋找答案,但沒有人遇到同樣的問題。這個問題看起來可能與此處的另一個問題相同,但它絕對不是:)Android ViewPager,碎片和AsyncTask。如何保持AsyncTask在方向更改上的狀態?
基本上我想創建的是一個「首次啓動」活動,由4個不同佈局的片段組成。這我已經做到了。我還有一個AsyncTask,通過調用遠程服務器來檢查一個片段是否存在於數據庫中。這也適用。但是,只要我旋轉手機和方向更改FragmentActivity重新創建(顯然=))。如果我在解僱AsyncTask時這樣做,它會崩潰或在某些情況下完成用戶檢查。
所以我的問題是:如果方向更改,我如何保留AsyncTask的狀態? 我見過一些使用回調的基本解決方案,並將AsyncTask作爲內部類。由於我的尋呼機適配器的佈局以及所創建的所有四個片段都使用了相同的Fragments類,因此它們不適用於我的情況。
任何幫助,非常感謝。示例或解決方案更值得讚賞! =)
請參閱下面的(醜陋)代碼,使所有這些都變成現實。
FirstRunActivity.java
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.iqqn.***.R;
import com.viewpagerindicator.IconPageIndicator;
import com.viewpagerindicator.PageIndicator;
public class FirstRunActivity extends SherlockFragmentActivity {
private FragmentAdapter mAdapter;
private ViewPager mPager;
private PageIndicator mIndicator;
private boolean userExit = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first_run);
mAdapter = new FragmentAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mIndicator = (IconPageIndicator)findViewById(R.id.indicator);
mIndicator.setViewPager(mPager);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.first_run, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_exit:
userExit = true;
this.finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
};
@Override
public void finish() {
// Prepare data intent
Intent data = new Intent();
if(userExit) {
data.putExtra("exit", true);
setResult(RESULT_CANCELED, data);
} else {
data.putExtra("signedIn", true);
data.putExtra("registered", true);
data.putExtra("acceptedEULA", true);
// Activity finished ok, return the data
setResult(RESULT_OK, data);
}
super.finish();
}
}
FragmentAdapter.java
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import com.iqqn.***.R;
import com.viewpagerindicator.IconPagerAdapter;
class FragmentAdapter extends FragmentPagerAdapter implements IconPagerAdapter {
protected static final int[] CONTENT = new int[] { R.layout.***_welcome_1, R.layout.***_welcome_2, R.layout.***_welcome_3, R.layout.***_welcome_4};
protected static final String[] CONTENTTITLE = new String[] { "Welcome","Account","Intro","Let's start!" };
protected static final int[] ICONS = new int[] {
R.drawable.perm_group_calendar,
R.drawable.perm_group_camera,
R.drawable.perm_group_device_alarms,
R.drawable.perm_group_location
};
private int mCount = CONTENT.length;
public FragmentAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return Fragments.newInstance(CONTENT[position % CONTENT.length],position);
}
@Override
public int getCount() {
return mCount;
}
@Override
public CharSequence getPageTitle(int position) {
return FragmentAdapter.CONTENTTITLE[position % CONTENT.length];
}
@Override
public int getIconResId(int index) {
return ICONS[index % ICONS.length];
}
public void setCount(int count) {
if (count > 0 && count <= 10) {
mCount = count;
notifyDataSetChanged();
}
}
}
Fragments.java
public final class Fragments extends SherlockFragment {
private static final String KEY_CONTENT = "Fragments:Content";
private int position = -1;
private RegisterAsyncTaskHelper registerTask = null;
public static Fragments newInstance(int content, int position) {
Fragments fragment = new Fragments();
fragment.mContent = content;
fragment.position = position;
return fragment;
}
private int mContent = -1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
if ((savedInstanceState != null) && savedInstanceState.containsKey(KEY_CONTENT)) {
mContent = savedInstanceState.getInt(KEY_CONTENT);
}
}
@Override
public void onPause() {
super.onPause();
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onDestroy() {
if (registerTask != null) {
registerTask.cancel(false);
}
super.onDestroy();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(mContent, container, false);
switch(position) {
case 0:
break;
case 1:
final Button btnRegister;
final Button btnLinkToLogin;
btnRegister = (Button) view.findViewById(R.id.btnRegister);
btnLinkToLogin = (Button) view.findViewById(R.id.btnLinkToLoginScreen);
// Register Button Click event
btnRegister.setOnClickListener(new View.OnClickListener() {
public void onClick(View localview) {
// Execute register task
registerTask = new RegisterAsyncTaskHelper(getActivity(), view);
if(registerTask != null)
registerTask.execute();
}
});
// Link to Login Screen
btnLinkToLogin.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
// TODO Login
}
});
break;
case 2:
break;
case 3:
break;
default:
break;
}
return view;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(KEY_CONTENT, mContent);
}
}
RegisterAsyncTaskHelper.java
import org.json.JSONException;
import org.json.JSONObject;
import android.os.AsyncTask;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.iqqn.***.R;
import com.iqqn.***.utils.DatabaseHandler;
import com.iqqn.***.utils.UserFunctions;
public class RegisterAsyncTaskHelper extends AsyncTask<Void, Integer, Void> {
// JSON Response node names
private static final String KEY_SUCCESS = "success";
private static final String KEY_ERROR = "error";
private static final String KEY_ERROR_MSG = "error_msg";
private static final String KEY_UID = "uid";
private static final String KEY_NAME = "name";
private static final String KEY_EMAIL = "email";
private static final String KEY_CREATED_AT = "created_at";
private View view = null;
private FragmentActivity activity = null;
private ProgressBar mProgress;
public RegisterAsyncTaskHelper(FragmentActivity activity, View view) {
this.view = view;
this.activity = activity;
this.mProgress = (ProgressBar) view.findViewById(R.id.registerProgress);
}
@Override
protected void onPreExecute() {
mProgress.setVisibility(View.VISIBLE);
}
@Override
protected Void doInBackground(Void... params) {
final EditText inputFullName;
final EditText inputEmail;
final EditText inputPassword;
final TextView registerErrorMsg;
// Importing all assets like buttons, text fields
inputFullName = (EditText) view.findViewById(R.id.registerName);
inputEmail = (EditText) view.findViewById(R.id.registerEmail);
inputPassword = (EditText) view.findViewById(R.id.registerPassword);
registerErrorMsg = (TextView) view.findViewById(R.id.register_error);
String name = inputFullName.getText().toString();
String email = inputEmail.getText().toString();
String password = inputPassword.getText().toString();
UserFunctions userFunction = new UserFunctions();
JSONObject json = userFunction.registerUser(name, email, password);
// check for login response
try {
if (json.getString(KEY_SUCCESS) != null) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
registerErrorMsg.setText("");
}
});
String res = json.getString(KEY_SUCCESS);
if(Integer.parseInt(res) == 1){
// user successfully registred
// Store user details in SQLite Database
DatabaseHandler db = new DatabaseHandler(activity.getApplicationContext());
JSONObject json_user = json.getJSONObject("user");
// Clear all previous data in database
userFunction.logoutUser(activity.getApplicationContext());
db.addUser(json_user.getString(KEY_NAME), json_user.getString(KEY_EMAIL), json.getString(KEY_UID), json_user.getString(KEY_CREATED_AT));
/*
// Launch Dashboard Screen
Intent dashboard = new Intent(ctx, DashboardActivity.class);
// Close all views before launching Dashboard
dashboard.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(dashboard);
// Close Registration Screen
finish();
*/
}else{
// Error in registration
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
registerErrorMsg.setText("Error occured in registration");
}
});
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onProgressUpdate(final Integer... values) {
}
@Override
protected void onPostExecute(final Void result) {
mProgress.setVisibility(View.GONE);
}
}
只是爲了澄清。截至目前,該代碼絕不應該看起來不錯。但它會在我得到這個工作之後。
//亞歷山大
謝謝CommonsWare!這個答案讓我明白,問題本身就是AsyncTask片段是不可保留片段的一部分。我最終使用了你提供的方法,並且完美:)我將編輯我的主帖,並在代碼看起來可用時立即提供解決方案。 –
當方向變化時重新創建Activity時,我們是否還應該在AsyncTask中更改Activity實例,並在Activity被銷燬時清除舊的? – Piotr
@Piotr:只要'AsyncTask'不直接保存到'Activity'實例,就會自動爲您處理。如果'AsyncTask'爲片段的活動詢問其封閉片段,它將會得到正確的片段。 – CommonsWare