我已经查看了其他问题,博客和文档,似乎找不到满足我需求的正确答案。 我有两个活动,A和B.当我启动活动B(来自A)时,我希望它立即打开,然后在显示进度条时加载所有内容,而不是仅在加载内容时打开活动,使其成为可能好像它冻结了两秒钟。 例如Youtube应用程序或Play商店。
这就是我得到的:
Button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent goB = new intent(ActivityA.this, ActivityB.class);
startActivity(goB);
}
});
这是我正在加载的活动
public class ActivityB extends AppCompatActivity implements OnDateSelectedListener, OnMonthChangedListener {
private static final DateFormat FORMATTER = SimpleDateFormat.getDateInstance();
@Bind(R.id.calendarView) MaterialCalendarView widget;
@Bind(R.id.textView) TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_c_calendar);
ButterKnife.bind(this);
widget.setOnDateChangedListener(this);
widget.setOnMonthChangedListener(this);
textView.setText(getSelectedDatesString());
}
@Override
public void onDateSelected(@NonNull MaterialCalendarView widget, @Nullable CalendarDay date, boolean selected) {
textView.setText(getSelectedDatesString());
}
private String getSelectedDatesString() {
CalendarDay date = widget.getSelectedDate();
if (date == null) {
return "No Selection";
}
return FORMATTER.format(date.getDate());
}
@Override
public void onMonthChanged(MaterialCalendarView widget, CalendarDay date) {
}
}
我不是专家,所以欢迎详细解释。
注意:我在活动中加载的是这个calandar:https://github.com/prolificinteractive/material-calendarview
问题:如何在后台加载setContentView()
?
更新:我遵循了Hitesh Sahu的建议,现在我只有一个活动,每个片段都有一个容器被替换,我假设加载xml的方法对于片段和活动,背景中的内容将是相同的,但如果有任何差异,请提及。
答案 0 :(得分:5)
可能的解决方案
来自"我不是专家" 我的猜测是,您可能会在每次切换屏幕时创建新活动,并且可能无法清除旧活动或重复使用现有活动。再次,这是我的猜测,我没有看到你的代码,但我看到开发人员犯了这样的错误。很快,你的应用程序的性能会随着时间的推移而降低,你的应用程序将最终吃掉内存。
如何修复: - 将活动替换为片段切换片段比切换活动相对快,而且可以重复使用它们({{ 3}})。
您可能正在主Ui线程上执行一些繁重的任务,查找more about this日志,例如 - skipped n number of frames app may be doing too much work on main thread
如何解决此问题: - 已在其他答案中说明。
答案 1 :(得分:3)
您需要使用AsyncTask
来加载数据,并使用RelativeLayout
在ActivityB
中显示舍入圆。
首先初始化变量
private RelativeLayout mRelativeLayout;
并在您的活动的onCreate
中执行AsyncTask
,就像这样
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRelativeLayout = (RelativeLayout) findViewbyID(R.id.loadingCircle);
new PrepareData().execute();
}
将此AsyncTask
课程放在ActivityB
private class PrepareData extends AsyncTask<Void, Void, Void> {
protected void onPreExecute(Void param) {
// THIS WILL DISPLAY THE PROGRESS CIRCLE
mRelativeLayout.setVisibility(View.VISIBLE)
}
protected Void doInBackground(Void... param) {
// PUT YOUR CODE HERE TO LOAD DATA
return null;
}
protected void onPostExecute(Void param) {
// THIS WILL DISMISS CIRCLE
mRelativeLayout.setVisibility(View.GONE)
}
并在XML
中包含此布局
为了在不使用对话框的情况下获取ProgressBar
,请使用此
<RelativeLayout
android:id="@+id/loadingCircle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
android:gravity="center" >
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true" />
</RelativeLayout>
并分别在RelativeLayout
和onPreExecute
中设置此onPostExecute
的可见性,就像我在示例中所示。
<强>更新强>
您需要更新Ui
中的UiThread
runOnUiThread(new Runnable() {
@Override
public void run() {
//put the code here that is giving exception
}
});
答案 2 :(得分:3)
您可以使用AsyncTask。
例如:在活动页面中添加(在onCreate()之外)。
class OnLoading extends AsyncTask<Void,Void,Void>{
ProgressDialog pd;
@Override
protected void onPreExecute() {
super.onPreExecute();
pd=new ProgressDialog(Main2Activity.this);
pd.setTitle("Title");
pd.setMessage("Message");
pd.setCancelable(false);
pd.show();
}
@Override
protected Void doInBackground(Void... params) {
//
//Do all your loading stuff here
//
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
pd.dismiss();
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
此类通过调用
执行new OnLoading().execute();
执行此代码时,执行的第一个函数将是 onPreExecute-&gt; doInBackGround-&gt; onPostExecute。。进度更新可用于通过调用
显示doInBackGround函数的一些进度publishProgress(value);
首先显示ProgressDialog。提供在doInBackground中加载数据等的代码。顾名思义,您在此函数中编写的任何内容都将在后台执行。在此函数完成执行后,将在onPostExecute()中取消进度对话框。
答案 3 :(得分:2)
您的活动B应该有AsyncTask来加载数据然后显示它。
您还可以在OnPreExecute()
@Override
protected void onCreate(Bundle savedInstanceState) {
setupViews();
}
private void setupViews(){
someView1 = (TextView) findViewById(R.id.some_view_id1);
someView2 = (TextView) findViewById(R.id.some_view_id2);
someView3 = (ImageView) findViewById(R.id.some_view_id3);
progressBar = (ProgressBar) findViewById(R.id.progress_bar_id);
new LoadDataForActivity().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private class LoadDataForActivity extends AsyncTask<Void, Void, Void> {
String data1;
String data2;
Bitmap data3;
@Override
protected void onPreExecute() {
progressBar.setVisibility(View.VISIBLE);
}
@Override
protected Void doInBackground(Void... params) {
data1 = loadData1();
data2 = loadData2();
data3 = loadData3();
}
@Override
protected void onPostExecute(Void result) {
someView1.setText(data1);
someView2.setText(data2);
someView3.setImageBitmap(data3);
progressBar.setVisibility(View.GONE);
}
}
答案 4 :(得分:1)
只需输入此代码:
Intent goB = new intent(ActivityA.this, ActivityB.class);
startActivity(goB);
在A的onCreate中。然后创建一个类似于此处显示的ProgressDialog:http://www.tutorialspoint.com/android/android_progressbar.htm
这将显示B加载的进度。你会打电话给
progress.setProgress(int)
在做完之后,在B's onCreate中。
例如:
public class B extends Activity {
public void onCreate(Bundle bundle) {
progress=new ProgressDialog(this);
progress.setMessage("Downloading Music");
progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progress.setIndeterminate(true);
progress.setProgress(0);
progress.show();
//do something
progress.setProgress(1);
//do something
progress.setProgress(2);
//do something different
progress.setProgress(3);
}
.....
修改
以下是使用ProgressBar执行此操作的方法:
ProgressBar
添加到B布局ProgressBar
中使用onCreate
findViewById()
ProgressBar
更新setProgress(int)
(如ProgressDialog
问题的第一部分所示)ProgressBar
ProgressBar.setVisibility(View.GONE)
答案 5 :(得分:1)
听起来你在onCreate
函数中正在做所有事情(包括繁重的加载)。请查看Activity life cycle 并考虑将代码放入,例如onStart
或onResume
。此外,重物可以放在worker thread上。这个keeps your UI responsive和用户更开心。
答案 6 :(得分:0)
首先以
开始您的活动startActivity(new intent(A.this, B.class));
从您选择的任何事件中,接下来是您的活动B的工作方式。
class B extends AppCompatActivity implements OnDateSelectedListener, OnMonthChangedListener {
private static final DateFormat FORMATTER = SimpleDateFormat.getDateInstance();
@Bind(R.id.calendarView) MaterialCalendarView widget;
@Bind(R.id.textView) TextView textView;
ProgressDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
if(!B.this.isFinishing() && progressDialog != null && !progressDialog.isShowing()) {
progressDialog.show();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
ButterKnife.bind(B.this);
widget.setOnDateChangedListener(B.this);
widget.setOnMonthChangedListener(B.this);
textView.setText(getSelectedDatesString());
if(!B.this.isFinishing() && progressDialog != null && progressDialog.isShowing()) {
progressDialog.hide();
}
}, 1500);
}
@Override
public void onDateSelected(@NonNull MaterialCalendarView widget, @Nullable CalendarDay date, boolean selected) {
textView.setText(getSelectedDatesString());
}
private String getSelectedDatesString() {
CalendarDay date = widget.getSelectedDate();
if (date == null) {
return "No Selection";
}
return FORMATTER.format(date.getDate());
}
@Override
public void onMonthChanged(MaterialCalendarView widget, CalendarDay date) {
}
}
编辑:@ Andre99显示使用进度条:
- 将ProgressBar添加到B布局
-get在B的onCreate中引用此ProgressBar(使用findViewById()
每次使用setProgress(int)更新ProgressBar(如ProgressDialog问题的第一部分所示)
- 使用yourProgressBar.setVisibility(View.GONE)隐藏你的ProgressBar
答案 7 :(得分:0)
对于您不需要立即显示的所有内容,您应该使用ViewStub。从XML布局中扩展视图可能是一项非常昂贵的操作,特别是如果您有多个嵌套的ViewGroup。 ViewStub的工作原理是将onCreate()的不必要的布局通胀抵消到您选择的位置,这会转换为您在屏幕上显示的活动更快。
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="match_parent"
android:indeterminate="true"
android:layout_height="match_parent"/>
<ViewStub
android:id="@+id/view_stub"
android:inflatedId="@+id/calendarView"
android:layout="@layout/my_expensive_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
现在ProgressBar显示在屏幕上,我们可以在onCreate()之后的生命周期调用中膨胀ViewStub,例如onPostCreate()或onResume()。您可以使用以下方法实现此目的:
viewStub.setOnInflateListener(new OnInflateListener() {
void onInflate(ViewStub stub, View inflated) {
calendarView = (MaterialCalendarView) inflated.findViewById(R.id.calendarView);
// perform any calendar setup here
progressBar.setVisibility(View.GONE); // hide progressbar, no longer needed
}
});
viewStub.inflate();
绝对值得检查您的View层次结构,并在可能的情况下简化任何嵌套的ViewGroup,因为这在查看性能时确实会受到影响。如果整个应用程序运行缓慢,则可能表示内存泄漏等问题较多,您可以使用LeakCanary检测到这些问题。
答案 8 :(得分:0)
您可以尝试以下代码:
Intent intent= new Intent(currentActivity.this, targetActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
希望,它会正常运作。祝你好运。