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

Java android:立即启动一项活动,然后加载内容,java,android,android-activity,Java,Android,Android Activity,我研究了其他问题、博客和文档,似乎找不到适合我需求的正确答案。 我有两个活动,A和B。当我启动活动B(从A开始)时,我希望它立即打开,然后在显示进度条的同时加载所有内容,而不是仅在加载内容时打开活动,使其看起来冻结了两秒钟。 例如Youtube应用程序或Play商店 这就是我得到的: Button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v

我研究了其他问题、博客和文档,似乎找不到适合我需求的正确答案。 我有两个活动,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) {

    }

}
这是我正在加载的活动:

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) {

    }

}
我不是专家,所以欢迎详细解释

注意:我在活动中加载的是此日历:

问题:如何在后台加载
setContentView()

更新:我听从了Hitesh Sahu的建议,现在我只有一个活动和一个容器,每个片段都会被替换,我假设在后台加载xml内容的方式对于片段和活动是相同的,但是如果有任何不同,请提一提。

只需输入以下代码:

Intent goB = new intent(ActivityA.this, ActivityB.class);
startActivity(goB);
在A的onCreate中。然后创建如下所示的ProgressDialog:

这将显示B加载的进度。你会打电话的

progress.setProgress(int)
在B的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的
    onCreate
    中获取对该
    ProgressBar
    的引用(使用
    findViewById()
  • 随时用
    setProgress(int)
    更新
    ProgressBar
    (如
    ProgressDialog
    问题的第一部分所示)
  • 使用
    ProgressBar.setVisibility(View.GONE)

听起来你什么都在做(包括重载的东西)在<代码> OnCudio函数中,查看并考虑将代码放在例如<代码> OnStuts或OnCudio中。此外,重物可以放在A上。这和用户更高兴。

< p>需要使用<代码>异步任务< /代码>加载数据和<代码> RelialayOut< <代码>以显示舍入圆。在
活动b

第一次初始化变量

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();
}
runOnUiThread(new Runnable() {
 @Override
 public void run() {

 //put the code here that is giving exception

    }
});
将此
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)
}
并分别在
onPreExecute
onPostExecute
中设置此
RelativeLayout
的可见性,如示例中所示

更新:

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) {

    }

}
您需要像这样更新
UiThread
中的
Ui

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mRelativeLayout = (RelativeLayout) findViewbyID(R.id.loadingCircle);

    new PrepareData().execute();
}
runOnUiThread(new Runnable() {
 @Override
 public void run() {

 //put the code here that is giving exception

    }
});

首先,开始你的活动

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布局

-在B的onCreate中获取对此ProgressBar的引用(使用findViewById()

-随时用setProgress(int)更新进度条(如ProgressDialog问题的第一部分所示)


-使用ProgressBar.setVisibility(View.GONE)隐藏ProgressBar

您的活动B应该有一个AsyncTask来加载数据,然后显示数据。 您还可以在
OnPreExecute()的视图中加载一些默认数据

@覆盖
创建时受保护的void(Bundle savedInstanceState){
setupview();
}
私有void setupViews(){
someView1=(TextView)findViewById(R.id.some\u view\u id1);
someView2=(TextView)findViewById(R.id.some\u view\u id2);
someView3=(ImageView)findViewById(R.id.some\u view\u id3);
progressBar=(progressBar)findViewById(R.id.progress\u bar\u id);
new LoadDataForActivity().executeOnExecutor(AsyncTask.THREAD\u POOL\u EXECUTOR);
}
私有类LoadDataForActivity扩展了AsyncTask{
字符串数据1;
字符串数据2;
位图数据3;
@凌驾
受保护的void onPreExecute(){
progressBar.setVisibility(View.VISIBLE);
}
@凌驾
受保护的Void doInBackground(Void…参数){
data1=loadData1();
data2=loadData2();
data3=loadData3();
}
@凌驾
受保护的void onPostExecute(void结果){
someView1.setText(data1);
someView2.setText(data2);
someView3.setImageBitmap(数据3);
progressBar.setVisibility(View.GONE);
}
}
可能的解决方案

  • 来自“我不是专家”我的猜测是,您可能会在每次屏幕切换时创建新的活动,可能不会清除旧的活动或重用现有的活动。同样,我的猜测是,我没有看到您的代码,但我看到开发人员犯过这种错误。很快,您的应用程序的性能会随着时间的推移而降低,并且最终会消耗内存

    如何解决此问题:-将活动替换为片段切换片段相对比切换活动快,而且您可以重用它们()

  • 您可能正在主Ui线程上执行一些繁重的任务查找日志,如-
    skipped n number of frames app可能在主线程上执行了太多工作

    如何解决此问题:-已在其他答案中解释

对于不需要立即显示的所有内容,都应该使用。从XML布局中膨胀视图可能是一项非常昂贵的操作,尤其是当您有多个嵌套的视图组时。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>
这绝对值得检查您的视图层次结构,并尽可能简化任何嵌套的视图组,因为这在视图性能方面确实会造成影响。
publishProgress(value);