Як перезапустити Діяльність в Android


381

Як перезапустити Android Activity? Я спробував наступне, але Activityпросто вийшов.

public static void restartActivity(Activity act){

        Intent intent=new Intent();
        intent.setClass(act, act.getClass());
        act.startActivity(intent);
        act.finish();

}

9
активність припиняється, оскільки u називається "act.finish ();" одразу після створення діяльності ...
— Ніхіл Дінеш

1
застарілий метод
— pedjjj

Відповіді:


623

Я зробив свій перемикач тем так:

Intent intent = getIntent();
finish();
startActivity(intent);

В основному я дзвоню finish()першим, і я використовую точно такий самий намір, з якого розпочалась ця діяльність. Це, здається, робить трюк?

ОНОВЛЕННЯ: Як зазначав Ральф нижче, Activity.recreate()це спосіб перейти в API 11 і далі. Це краще, якщо ви перебуваєте в середовищі API11 +. Ви все ще можете перевірити поточну версію та зателефонувати за фрагментом коду вище, якщо ви перебуваєте в API 10 або нижче. (Будь ласка, не забудьте підтримати відповідь Ральфа!)


36
І це варто брати до уваги? Це не була вимога, про яку йдеться в ОП. Насправді це може бути бажаним.
— EboMike

9
Ну, якщо анімація вам не подобається, ви можете вимкнути її (як ви продемонстрували у своїй відповіді). Це не робить мою відповідь неправильною, вона просто не показує додаткові параметри, які ви можете безкоштовно додати (і про це не вимагали у запитанні).
— EboMike

28
Думаю, ти помилився. Відхилення означає неправильну / погану відповідь, а оновлення означає, що відповідь чудова. Наскільки велика відповідь у порівнянні з іншими, вказується кількість заявок. Я бачу, що ви намагаєтесь просувати свою відповідь, але ви зловживаєте системою для цієї мети.
— EboMike

8
+1 - для мене це спрацювало чудово, і, як ви кажете, анімація - це те, що я хотів, тому користувач знає, що вона перезапускається. FWIW, я приймаю за правило ніколи не відмовлятись від відповідей інших користувачів, коли я надаю альтернативну відповідь на питання, хоча я періодично піднімаю голос, коли моя відповідь перекреслена (не кажучи, що це сталося тут, тільки що я це роблю) .
— Майкл Брей

4
EboMike та Ben: Обидва ваші рішення відповіли на питання ОП. Озвучувати чиюсь відповідь виключно з "естетичної" причини, ну, не дуже. Я б заважав комусь робити це тут, у Стаковерфлі ...
— ChuongPham

368

Оскільки API рівня 11 (стільник), ви можете викликати метод відтворення () діяльності (завдяки цій відповіді).

Метод recreate () діє так само, як і зміна конфігурації, тому ваші методи onSaveInstanceState () та onRestoreInstanceState () також викликаються, якщо це застосовується.


3
що робити, якщо попередня діяльність називала цю за допомогою startActivityForResult?
— андроїд розробник

1
Ну, це правильна відповідь, якщо вам не потрібно підтримувати щось нижче, ніж API 11.
— Едвард Фолк

@EdwardFalk чи є якась функція, яка виконує це в бібліотеці підтримки?
— андроїд розробник

2
Це працює не у всіх випадках. Якщо у вас відкритий ящик навігації під час виклику recreate (), він буде залишатися відкритим при відтворенні, а це означає, що він зберігає стан, що може бути не бажаним.
— Чапз

Я той, хто не хоче врятувати державу. Іноді люди просто хочуть чистого перезапуску, тоді вони повинні використовувати відповідь EboMike.
— Кімі Чіу

132

Перед SDK 11 спосіб зробити це так:

public void reload() {
    Intent intent = getIntent();
    overridePendingTransition(0, 0);
    intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
    finish();
    overridePendingTransition(0, 0);
    startActivity(intent);
}

На HTC Desire анімації все ще залишаються (принаймні, коли вони використовуються в методі onConfigurationChanged). Вони трапляються не завжди, але, використовуючи код EboMike, вони також не завжди.
— Юозас Контвайніс

8
Це не працює на основній діяльності, розпочатої пусковим пристроєм. Ваша діяльність закінчиться прихованою через деякі прапори, встановлені на намірі. Інакше це чудово працює.
— Томас Ейл

Гарна думка. має сенс, оскільки він називає закінчення () з базової активності в стеку.
— Бен

Якщо зателефонувати цьому, коли ми змінимо тему діяльності, схоже, з’явиться швидкість (без анімації)
— Ашок Голі

3
+1 Добре працює для мене навіть з основною діяльністю. Однак вам слід зателефонувати overridePendingTransition(0, 0);після finish()і startActivity(), відповідно, не там, де ви його подзвонили ...
— caw

115

Просто для поєднання відповідей Ральфа та Бена (включаючи зміни, внесені в коментарях):

if (Build.VERSION.SDK_INT >= 11) {
    recreate();
} else {
    Intent intent = getIntent();
    intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
    finish();
    overridePendingTransition(0, 0);

    startActivity(intent);
    overridePendingTransition(0, 0);
}

8
Найкраща відповідь усіх. Вірите чи ні, я все ще підтримую пристрої API 3, і для значення VERSION.SDK_INT потрібен API 4. :)
— Edward Falk

31

Я використовував цей код, щоб я міг підтримувати старіші версії Android та використовувати recreate()новіші версії Android.

Код:

public static void restartActivity(Activity activity){
    if (Build.VERSION.SDK_INT >= 11) {
        activity.recreate();
    } else {
        activity.finish();
        activity.startActivity(activity.getIntent());
    }
}

Зразок:

import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
    private Activity mActivity;

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

        mActivity = MainActivity.this;

        Button button = (Button) findViewById(R.id.restart_button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                restartActivity(mActivity);
            }
        });
    }

    public static void restartActivity(Activity activity) {
        if (Build.VERSION.SDK_INT >= 11) {
            activity.recreate();
        } else {
            activity.finish();
            activity.startActivity(activity.getIntent());
        }
    }
}

це велика робота для мене !!
— папо

22

Це рішення спрацювало на мене.

Спочатку закінчіть діяльність, а потім почніть її знову.

Приклад коду:

public void restartActivity(){
    Intent mIntent = getIntent();
    finish();
    startActivity(mIntent);
}

20

Це, безумовно, найпростіший спосіб відновити поточну діяльність:

finish();
startActivity(getIntent());

19

Викличте цей метод

private void restartFirstActivity()
 {
 Intent i = getApplicationContext().getPackageManager()
 .getLaunchIntentForPackage(getApplicationContext().getPackageName() );

 i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
 startActivity(i);
 }

Дякую,


1
Я думаю, що ОП хоче відновити будь-яку діяльність, не лише першу, але це було мені корисно.
— Крістофер Джонсон

1
Два прапори добре знати, мій випадок, здавалося, без них нічого не робить.
— Оуен Б

1
це спрацювало завдяки вам! Бог благословив тебе.
— Вівек

16

Хоча на це відповіли неодноразово.

Якщо перезапустити діяльність з фрагмента, я б це зробив так:

new Handler().post(new Runnable() {

         @Override
         public void run()
         {
            Intent intent = getActivity().getIntent();
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION);
            getActivity().overridePendingTransition(0, 0);
            getActivity().finish();

            getActivity().overridePendingTransition(0, 0);
            startActivity(intent);
        }
    });

Тож ви можете подумати, що це трохи непосильне? Але Handlerпублікація дозволяє викликати це методом життєвого циклу. Я використовував це в onRestart/ onResumeметодах, коли перевіряв, чи змінився стан між користувачем, який повертається до програми. (щось встановлено).

Без цього, Handlerякщо ви зателефонуєте в незвичне місце, він просто знищить діяльність, а не перезапустить її.

Сміливо задайте будь-які питання.

Ура, Кріс


2
Прекрасне рішення та дуже хороші міркування / пояснення для обробника.
— JRomero

1
Чому ви дзвоніть двічі на "overridePendingTransition"?
— андроїд розробник

1
@androiddeveloper Я не можу згадати, я думаю, що це була проблема з помилкою. Ви можете зателефонувати йому один раз до запуску startActivity (), і він буде робити так, як сказано.
— Кріс Дженкінс

Після втілення цього в мою функцію onResume гра зупиняється на моєму методі onStop і має чорний екран ... не впевнений чому
— Scumble373

1
Вітаю, Кріс, чи можеш ти пояснити це трохи далі "Без обробника, якщо ви зателефонуєте йому в непарному місці, це просто вб'є діяльність та не перезапустить її". ?
— parvez rafi

15

Ну, це не в списку, але комбінація деяких, які вже розміщені:

if (Build.VERSION.SDK_INT >= 11) {
    recreate();   
} else {
    Intent intent = getIntent();
    finish();
    startActivity(intent);
}

Це працює для мене .. дякую .. але я хочу запитати вас: чому коли я видаляю першу частину коду (ту, що перевіряє SDK_INT), моя програма працює, відносно, повільно? !! .. коли я знову прикріплюю код знову він працює, відносно і очевидно, набагато швидше !!!
— Маклан

2
Не впевнений у цьому. Добре, якщо ви використовуєте SDK, який становить> = 11, то відтворення () має бути швидшим, ніж отримання наміру, закінчення, а потім його запуск знову. Закінчити код виклику, який працює на onStop, і відтворити код запуску, як зміна орієнтації ... так що це не так вже й багато.
— Кодований

4

У поєднанні з дивною поведінкою життєвого циклу SurfaceView з камерою . Я виявив, що відтворити () не дуже добре поводиться з життєвим циклом SurfaceViews. surfaceDestroyed ніколи не викликається під час циклу відпочинку. Він викликається після onResume (дивно), в цей момент мій SurfaceView знищується.

Оригінальний спосіб відтворення діяльності чудово працює.

Intent intent = getIntent();
finish();
startActivity(intent);

Я не можу точно зрозуміти, чому це так, але це лише спостереження, яке, сподіваюся, може керувати інших у майбутньому, оскільки воно виправляло мої проблеми, які у мене виникали з SurfaceViews


4

Цікаво, чому ніхто не згадав, Intent.makeRestartActivityTask()що чітко робить цю точну мету.

Зробіть намір, який можна використовувати для повторного запуску завдання програми * у його базовому стані.

startActivity(Intent.makeRestartActivityTask(getActivity().getIntent().getComponent()));

Цей метод встановлює Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASKяк прапори за замовчуванням.


3

Насправді наступний код є дійсним для рівнів API 5 і вище, тому якщо ваш цільовий API нижчий за цей, ви отримаєте щось дуже схоже на код EboMike.

intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
overridePendingTransition(0, 0);

3

Є один хакітний спосіб, який повинен працювати на будь-якій діяльності, включаючи основну.

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

Коли орієнтація змінюється, Android, як правило, відтворить вашу активність (якщо ви не перекриєте її). Цей метод корисний для обертів на 180 градусів, коли Android не відтворює вашу активність.


3
public void onRestart() {
    super.onRestart();
    Intent intent=new Intent();
    intent.setClass(act, act.getClass());
    finish();
    act.startActivity(intent);
}

спробуйте скористатися цим ..


3

Рішення вашого питання:

public static void restartActivity(Activity act){
    Intent intent=new Intent();
    intent.setClass(act, act.getClass());
    ((Activity)act).startActivity(intent);
    ((Activity)act).finish();
}

Вам потрібно привласнити контекст діяльності, щоб розпочати нову діяльність, а також закінчити поточну діяльність.

Сподіваюся, це корисно .. і працює для мене.


1

Якщо ви видалите останній рядок, ви створите нову actактивність, але ваш старий екземпляр все ще буде живим.

Вам потрібно перезапустити Діяльність, наприклад, коли зміна орієнтації (тобто ваш стан зберігається і передається onCreate(Bundle))?

Якщо ви цього не зробите, одним із можливих варіантів вирішення проблеми буде використання однієї додаткової фіктивної діяльності, яка буде розпочата з першої діяльності, і завданням якої є запуск нового її примірника. Або просто затримати дзвінок наact.finish() після запуску нового.

Якщо вам потрібно зберегти більшу частину штату, ви потрапляєте у досить глибокі води, тому що нетривіально передавати всі властивості своєї держави, особливо не витікаючи ваш старий контекст / діяльність, передаючи його новій інстанції.

Вкажіть, будь ласка, що ви намагаєтесь зробити.


1
У мене є кнопка, яка застосовує різні теми до програми, після того як тема буде застосована, вона зберігається в уподобанні, коренева активність відновлюється, читає тему з уподобань, застосовує тему в onCreate (). Виявляється, вищевказаний код працює нормально, якщо активність не є однією речовиною. Не впевнений, чи це найкраща практика.

Наразі не існує чистого, заповненого SDK способу перезапустити свою активність, AFAIK - якщо ви нічого не просочитеся, можливо, будете добре їхати :)
— Димитар Димитров

0

Це так, як я це роблю.

        val i = Intent(context!!, MainActivity::class.java)
        i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
        startActivity(i)

-1

Якщо ви телефонуєте з якогось фрагмента, то зробіть нижче код.

Intent intent = getActivity().getIntent();
getActivity().finish();
startActivity(intent);

-4

ви можете просто використовувати

onRestart ()

метод наступним чином

 @Override
    protected void onRestart() {
        super.onRestart();
        setContentView(R.layout.add_entry);
    }

і зателефонуйте onRestart (), де ви хочете перезапустити поточну активність


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.