2

首先; 是的,我到处都在寻找这个问题的答案,但没有人遇到过和我一样的问题。这个问题似乎与此处的另一个问题相同,但绝对不是:)

基本上我想要创建的是一个“First-start”活动,它由 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();
} 
}

片段适配器.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();
    }
}
}

片段.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);
}
}

只是为了澄清。到目前为止,这段代码不应该看起来很好。但它会在我得到这个工作之后。

// 亚历山大

4

4 回答 4

2

如果方向发生变化,如何保留 AsyncTask 的状态?

由保留AsyncTask的片段(即调用setRetainInstance(true)自身的动态片段)管理。该片段将在配置更改后继续存在。

由于我的寻呼机适配器的布局以及相同的 Fragments 类用于创建的所有四个片段的事实,它们在我的情况下不起作用。

然后为AsyncTask. 它不必参与 UI:

if (getSupportFragmentManager().findFragmentByTag(MODEL)==null) {
  model=new ModelFragment();
  getSupportFragmentManager().beginTransaction().add(model, MODEL)
                             .commit();
}

在这里,ModelFragment负责(以及活动所需的数据模型FragmentAsyncTask任何部分,而不是保存在其他任何地方的内存中)。MODEL我们仅在其标签 ( )下不存在该片段时才创建该片段。

于 2012-11-20T22:41:08.260 回答
1

使用AsyncTaskLoader保存任务的状态和结果。

于 2012-11-20T22:28:46.160 回答
0

在目标片段中使用意图服务和LocalBroadcastManager

于 2012-11-20T22:44:54.867 回答
0

我在这种情况下所做的是使用BroadcastReceiver. AsyncTask我建议不要将 your与 your紧密耦合FragmentActivity,而是建议使用 aThread来运行您的后台操作和调用context.sendBroadcast(...),然后在您的FragmentActivity.

于 2012-11-20T22:32:10.933 回答