web-dev-qa-db-de.com

android: Starten Sie sofort eine Aktivität und laden Sie dann den Inhalt

Ich habe mir andere Fragen, Blogs und die Dokumentation angesehen und kann anscheinend nicht die richtige Antwort auf meine Bedürfnisse finden. Ich habe zwei Aktivitäten, A und B. Wenn ich mit Aktivität B (von A) beginne, habe ich Ich möchte, dass er sofort geöffnet wird und dann den gesamten Inhalt mit einer Fortschrittsleiste lädt, anstatt die Aktivität nur zu öffnen, wenn der Inhalt geladen ist, sodass er so aussieht, als würde er für zwei Sekunden eingefroren. Ein Beispiel wäre das Youtube App oder den Play Store.

Das habe ich bekommen:

Button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent goB = new intent(ActivityA.this, ActivityB.class);
            startActivity(goB);
        }
    });

Dies ist die Aktivität, die ich lade:

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

    }

}

Ich bin kein Experte, daher werden ausführliche Erklärungen begrüßt.

Hinweis: Was ich in der Aktivität lade, ist dieser Kalender: https://github.com/prolificinteractive/material-calendarview

Frage: Wie lade ich setContentView() in den Hintergrund?

Update: Ich habe den Rat von Hitesh Sahu befolgt und jetzt habe ich nur noch eine Aktivität mit einem Container, der für jedes Fragment ersetzt wird. Ich gehe davon aus, dass der Weg, den XML-Inhalt im Hintergrund zu laden, der gleiche ist Fragment und eine Aktivität, aber wenn es Unterschiede gibt, bitte erwähnen.

17
John Sardinha

Mögliche Lösung

  • Von "Ich bin kein Experte" Meine Vermutung ist, dass Sie auf jedem Bildschirmwechsel eine neue Aktivität erstellen und möglicherweise die ältere nicht löschen oder vorhandene Aktivitäten wiederverwenden können. Dies ist meine Vermutung, dass ich Ihren Code nicht gesehen habe, aber ich habe gesehen, dass Entwickler diese Art von Fehlern begangen haben. Die Leistung Ihrer App wird sich mit der Zeit verschlechtern, und Ihre App wird am Ende Speicher abfressen. 

    So beheben Sie das Problem: - Ersetzen Sie Aktivitäten mit Fragment Das Umschalten des Fragments ist relativ schneller als das Wechseln von Aktivitäten. Außerdem können Sie diese wiederverwenden ( mehr dazu ). .

  • Sie könnten eine schwere Aufgabe beim Suchen des Haupt-Ui-Threads nach choreographer logs wie - skipped n number of frames app may be doing too much work on main thread ausführen.

    So beheben Sie das Problem:- wurde bereits in anderen Antworten erläutert.

4
Hitesh Sahu

Sie müssen AsyncTask zum Laden von Daten und RelativeLayout für die Anzeige des Rundungskreises in ActivityB verwenden.

Initialisieren Sie zuerst die Variable

private RelativeLayout mRelativeLayout;

und führen Sie in onCreate Ihrer Aktivität AsyncTask so aus 

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

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

    new PrepareData().execute();
}

diese AsyncTask-Klasse in ActivityB setzen

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

und in XML dieses Layout einschließen

Um die ProgressBar ohne Dialog zu erhalten, verwenden Sie diese 

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

und legen Sie die Sichtbarkeit von this RelativeLayout in onPreExecute und onPostExecute fest, wie ich es im Beispiel gezeigt habe.

UPDATE:

sie müssen Ihre Ui in UiThread so aktualisieren 

runOnUiThread(new Runnable() {
 @Override
 public void run() {

 //put the code here that is giving exception

    }
});
2
Max

Ihre Aktivität B sollte über AsyncTask verfügen, um Daten zu laden und dann anzuzeigen. Sie können auch einige Standarddaten in der Ansicht von OnPreExecute() laden.

@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);
    }

}

Sie könnten eine AsyncTask verwenden.

ZB: Fügen Sie dies auf Ihrer Aktivitätsseite hinzu (außerhalb von 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);
}
}    

Diese Klasse wird durch Aufruf ausgeführt 

new OnLoading().execute();

Bei Ausführung dieses Codes wird die erste ausgeführte Funktion onPreExecute-> doInBackGround-> onPostExecute sein. . Die Fortschrittsaktualisierung kann verwendet werden, um den Fortschritt der doInBackGround-Funktion durch Aufrufen anzuzeigen 

publishProgress(value);

Hier wird zuerst der ProgressDialog angezeigt. Geben Sie den Code zum Laden der Daten usw. in doInBackground an. Da der Name impliziert, dass alles, was Sie in diese Funktion schreiben, im Hintergrund ausgeführt wird. Nachdem diese Funktion ausgeführt wurde, wird der Fortschrittsdialog in onPostExecute () geschlossen.

2
Akhil Soman

Gib einfach diesen Code ein:

Intent goB = new intent(ActivityA.this, ActivityB.class);
startActivity(goB);

In A ist onCreate. Dann erstellen Sie einen ProgressDialog wie den hier gezeigten: http://www.tutorialspoint.com/Android/android_progressbar.htm

Dies zeigt den Fortschritt des Ladens von B. Du wirst anrufen 

progress.setProgress(int)

in B's onCreate, nachdem Sie etwas getan haben.

Zum Beispiel:

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

BEARBEITEN

So können Sie eine ProgressBar verwenden:

  • fügen Sie dem Layout B ein ProgressBar hinzu
  • einen Verweis auf dieses ProgressBar in B's onCreate erhalten (mit findViewById()
  • aktualisieren Sie Ihre ProgressBar mit setProgress(int), wann immer Sie möchten (wie im ersten Teil der Frage für ProgressDialog gezeigt).
  • verstecken Sie Ihre ProgressBar mit Ihrer ProgressBar.setVisibility(View.GONE)
1
Andre99

Klingt so, als würden Sie alles (einschließlich der schweren Last) in der onCreate-Funktion ausführen. Sehen Sie sich den Lebenszyklus von Activity an und ziehen Sie in Betracht, Code in z. die onStart oder onResume. Schweres Zeug kann auch auf einen Worker Thread gestellt werden. Dadurch bleibt Ihre Benutzeroberfläche ansprechbar und der Benutzer ist zufriedener.

1
Gooey

Sie sollten einen ViewStub für alles verwenden, was nicht sofort angezeigt werden soll. Das Aufpumpen von Ansichten aus XML-Layouts kann recht aufwendig sein, insbesondere wenn Sie mehrere verschachtelte Ansichtsgruppen haben. Ein ViewStub wirkt, indem er unnötig layout inflation von onCreate () an einen Ort Ihrer Wahl versetzt, was zu einer schnelleren Aktivität auf dem Bildschirm führt.

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

Nun, da die Fortschrittsleiste auf dem Bildschirm angezeigt wird, können wir den ViewStub in einem Lebenszyklusaufruf nach onCreate () aufblasen, beispielsweise onPostCreate () oder onResume (). Sie können dies mit folgendem erreichen:

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();

Es lohnt sich auf jeden Fall, Ihre View-Hierarchie zu überprüfen und ggf. verschachtelte ViewGroups zu vereinfachen, da dies bei der Anzeige der Leistung wirklich zu einem Erfolg führen kann. Wenn Ihre gesamte App langsam ist, kann dies auf größere Probleme hinweisen, z. B. auf einen Speicherverlust, den Sie mit LeakCanary erkennen können.

0
fractalwrench

Beginnen Sie zunächst mit Ihrer Tätigkeit als

startActivity(new intent(A.this, B.class));

wie auch immer Sie sich für ein Ereignis entschieden haben, wie Ihre Aktivität B aussehen sollte.

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

  }
}

Edit: as @ Andre99 zeigte mit progressbar:

-addiere eine ProgressBar zum B-Layout

-Legen Sie einen Verweis auf diese ProgressBar in B's onCreate (mithilfe von findViewById ())

-update deine ProgressBar mit setProgress (int) wann immer du möchtest (wie im ersten Teil der Frage für ProgressDialog gezeigt)

-binden Sie Ihre ProgressBar mit yourProgressBar.setVisibility (View.GONE) aus

0
Akash Raghav

Sie können den folgenden Code ausprobieren:

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

Hoffe, es wird richtig funktionieren. Viel Glück.

0
user4356416