我很难完成一项应该很容易的任务。我不确定是不是因为Android平台设计不好或者我错过了什么。我只想在简历上刷新片段的视图。以下是详细信息:
我有两个活动,一个SplashActivity,它从服务器检索数据(使用AsyncTask)并将数据传递给我的MainActivity。在我的MainActivity中,我获取此数据并将其传递给名为SummaryFragment的片段。我有一些片段和一个导航抽屉(在我的MainActivity中)。第一个可见片段是SummaryFragment,它读取从MainActivity传递给它的数据,从而绘制图形。
当应用程序启动时,可能没有活动的Internet连接,在这种情况下,在我的摘要片段中,我要求用户启用WiFi。我想要做的是在用户启用WiFi后返回应用程序后刷新此SummaryFragment的视图。我现在做的是在我的MainActivity的onResume()中,我检查SummaryFragment是否可见,如果是,我再次启动SplashActivity(并关闭当前活动)。 SplashActivity必须获取数据(就像应用程序启动时一样)并启动MainActivity(用获取的数据提供),它加载摘要片段并显示图形。
问题是,在应用程序恢复后,需要相当长的时间(30-40秒)才能从SplashActivity转到MainActivity并显示图表(同时用户会看到启动屏幕),而当应用程序启动时,这需要1-2秒。在使用当前解决方案(将用户重定向到SplashActivity)之前,在MainActivity.onResume()中,我尝试使用我在SplashScreen中使用的相同AsyncTask类来获取数据并在之后显示摘要片段,但结果是相同的,有一个显着的延迟。
以下代码是我的MainActivity的onResume():
Fragment fragment = getVisibleFragment();
if (fragment instanceof SummaryFragment) {
Intent intentSplashActvity = new Intent(this, SplashActivity.class);
Log.d(TAG, "about to start the splash activity");
startActivity(intentSplashActvity);
// close current activity
finish();
super.onResume();
return;
}
super.onResume();
SplashActivity:
public class SplashActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash_screen);
new PrefetchData(this).execute();
}
}
PrefetchData:
public class PrefetchData extends AsyncTask<Void, Void, Void> {
String serverResponseJson = null;
private String data1 = null,
data2 = null,
data3 = null;
private SplashActivity mSplashActivity = null;
private MainActivity mMainActivity;
public PrefetchData(Activity sourceActivity){
if (sourceActivity.getClass() == SplashActivity.class) {
mSplashActivity = (SplashActivity) sourceActivity;
}
}
@Override
protected Void doInBackground(Void... arg0) {
JsonParser jsonParser = new JsonParser();
try {
if (CaratApplication.isInternetAvailable()) {
serverResponseJson = jsonParser
.getJSONFromUrl("http://aURL");
}
} catch (Exception e) {
Log.d("SplashActivity", e.getStackTrace().toString());
}
if (serverResponseJson != null && serverResponseJson != "") {
try {
JSONArray jsonArray = new JSONObject(serverResponseJson).getJSONArray("arrayName");
// Using Java reflections to set fields by passing their name to a method
try {
setFieldsFromJson(jsonArray, 0, "data1");
setFieldsFromJson(jsonArray, 1, "data2");
setFieldsFromJson(jsonArray, 2, "data3");
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
} catch (JSONException e) {
}
}
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (mSplashActivity != null) {
Intent intentMainActvity = new Intent(mSplashActivity, MainActivity.class);
if (gotDataSuccessfully()) {
intentMainActvity.putExtra("data1", data1);
intentMainActvity.putExtra("data2", data2);
intentMainActvity.putExtra("data3", data3);
} else {
intentMainActvity.putExtra("data1", Constants.DATA_NOT_AVAIABLE);
intentMainActvity.putExtra("data2", Constants.DATA_NOT_AVAIABLE);
intentMainActvity.putExtra("data3", Constants.DATA_NOT_AVAIABLE);
}
mSplashActivity.startActivity(intentMainActvity);
mSplashActivity.finish();
}
}
}
在MainActivity中,在导航抽屉中选择“summary”条目后,我初始化SummaryFragment,然后使用片段事务( replaceFragment(mSummaryFragment,mSummaryFragmentLabel))替换它。这是我用来初始化摘要片段的方法:
private void initSummaryFragment() {
if (mData1 == 0 && mData2 == 0 && mData3 == 0) {
Intent intent = getIntent();
String data1 = intent.getStringExtra("data1");
String data2 = intent.getStringExtra("data2");
String data3 = intent.getStringExtra("data3");
boolean isDataAvaiable = !data1.equals(Constants.DATA_NOT_AVAIABLE)
&& !data2.equals(Constants.DATA_NOT_AVAIABLE) && !data3.equals(Constants.DATA_NOT_AVAIABLE);
if (isDataAvaiable) {
mData1 = Integer.parseInt(data1);
mData2 = Integer.parseInt(data2);
mData3 = Integer.parseInt(data3);
}
}
mSummaryFragment = new SummaryFragment();
mArgs = new Bundle();
mArgs.putInt("data1", mData1);
mArgs.putInt("data2", mData2);
mArgs.putInt("data3", mData3);
mSummaryFragment.setArguments(mArgs);
mSummaryFragmentLabel = getString(R.string.summary);
}
SummaryFragment现在可以从传递给它的包中检索所需的数据。
答案 0 :(得分:0)
问题在于Android的AsyncTask的(相当)未记录的行为。 AsyncTask 不在单独的线程中运行,它在与其他AsyncTasks共享的线程中运行,因此如果您有其他AsyncTasks(或者甚至是普通线程),如果它们在当前之前开始运行AsyncTask,这个AsyncTask 等待让他们完成他们的行动。我明确指出我希望我的AsyncTask在一个单独的线程中运行,这样就可以将提取JSON对象的延迟从大约20-25秒减少到3-4秒(我正在进行其他并行的网络访问调用)。我在我的主要活动的onCreate()方法中运行以下代码作为我的preInitFragments()方法的一部分。
// The following PrefetchData class is of type AsyncTask<void, void, void>. I moved this class from a stand-alone class to an inner class inside my main activity for easier refreshing of my fragment.
PrefetchData prefetchData = new PrefetchData();
// run this asyncTask in a new thread [from the thread pool] (run in parallel to other asyncTasks)
// (do not wait for them to finish, it takes a long time)
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB)
prefetchData.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
prefetchData.execute();
在此之后我调用我的方法initSummaryFragment()。请注意,在我的AsyncTask中,在doInBackGround()中,我设置了你在下面看到的两个字段(mField1和mField2)(我曾经将它们作为一个包传递给摘要屏幕,但是当你刚才这样会导致问题分离和附加片段(以刷新其视图)而不将包传递给您的片段)。在我的asyncTask的onPostExecute()中,我调用了我的方法refreshSummaryFragment():
private boolean isStatsDataAvailable() {
return mWellbehaved != 0 && mHogs != 0 && mBugs != 0;
}
private void initSummaryFragment() {
if (! isStatsDataAvailable()) {
mSummaryFragment = new SummaryFragment();
}
mSummaryFragmentLabel = "Summary";
}
为了刷新我的摘要片段,我只需分离并附加我的摘要片段,然后提交挂起的片段事务:
public void refreshSummaryFragment() {
if (isStatsDataAvailable()) { // blank summary fragment already attached. detach and attach to refresh
FragmentManager manager = getSupportFragmentManager();
// init the fragment (for later use when user selects an item from the navigation drawer)
mSummaryFragment = getSupportFragmentManager().findFragmentByTag("Summary");
FragmentTransaction fragTransaction = manager.beginTransaction();
// refresh the summary fragment:
fragTransaction.detach(mSummaryFragment);
fragTransaction.attach(mSummaryFragment);
fragTransaction.commit();
} else {
Log.e(TAG, "refreshSummaryFragment(): stats data not avaiable!");
}
}