android:立即启动一个活动,然后加载内容

时间:2016-04-03 12:41:31

标签: java android android-activity

我已经查看了其他问题,博客和文档,似乎找不到满足我需求的正确答案。 我有两个活动,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的方法对于片段和活动,背景中的内容将是相同的,但如果有任何差异,请提及。

9 个答案:

答案 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来加载数据,并使用RelativeLayoutActivityB中显示舍入圆。

首先初始化变量

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>

并分别在RelativeLayoutonPreExecute中设置此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布局
  • 在B ProgressBar中使用onCreate
  • 引用此findViewById()
  • 每次根据ProgressBar更新setProgress(int)(如ProgressDialog问题的第一部分所示)
  • 使用ProgressBar
  • 隐藏ProgressBar.setVisibility(View.GONE)

答案 5 :(得分:1)

听起来你在onCreate函数中正在做所有事情(包括繁重的加载)。请查看Activity life cycle 并考虑将代码放入,例如onStartonResume。此外,重物可以放在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);

希望,它会正常运作。祝你好运。