Як перезапустити Діяльність в 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.