简体   繁体   中英

Activity layout lagging behind until before next transition to another activity

The problem is that, during transition from firstActivity to thisServiceActivity, the screen will freeze and then turn black. If service has performed it process and send the broadcast and receive by the broadcast receiver of thisServiceActivity, then it will finally show the layout of the thisServiceActivity and quickly transition to ResultActivity.

Is it because there is something I do wrong in its UI thread? I try to find similar discussion to this problem but can't find it.

firstActivity class will start a new activity which is thisServiceActivity class. thisServiceActivity have a layout that show a progressbar and textview. At the same time, it will start a service class name as myForegroundService with pending intent notification.

If the process in the service completed, the service will send a local broadcast that will be pickup by thisServiceActivity using broadcast receiver and it then stop the service and transition to resultActivity and finish its activity.

public class firstActivity extends AppCompatActivity {

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

    //using button onclick
    public void startActivity(View view) {
        Intent startService = new Intent(this, thisServiceActivity.class);
        startActivity(startService);
    }
}
package example.myapplication;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

public class thisServiceActivity extends AppCompatActivity {

    Intent goToResult, stopMyService, startMyService;

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

        LocalBroadcastManager.getInstance(this).registerReceiver(myForegroundReceiver, 
            new IntentFilter("end-of-process"));
        startService();
    }

    public void startService() {
        startMyService = new Intent(this, myForegroundService.class);
        ContextCompat.startForegroundService(this, startMyService);
    }

    public void stopService() {
        stopMyService = new Intent(this, myForegroundService.class);
        stopService(stopMyService);
    }

    @Override
    protected void onDestroy() {
        LocalBroadcastManager.getInstance(this).unregisterReceiver(myForegroundReceiver);
        super.onDestroy();
    }

    private BroadcastReceiver myForegroundReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i("onReceive", "Received");
            stopService();
            goToResult = new Intent(getApplication(), ResultActivity.class);
            startActivity(goToResult);
            finish();
        }
    };
}

package example.myapplication;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import java.util.concurrent.ExecutionException;

import static example.myapplication.App.CHANNEL_ID;

public class myForegroundService extends Service {

    Boolean process;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        Log.i("Service Running", "True");

        Intent toThisServiceActivity = new Intent(this, thisServiceActivity.class);
        PendingIntent servicePendingIntent = PendingIntent.getActivity(this, 0, toThisServiceActivity, 0);

        Notification notify = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("Sit back and relax, process is in progress")
                .setContentText("You look more charming if you have patient, please wait")
                .setContentIntent(servicePendingIntent)
                .build();

        startForeground(1, notify);

        try {
            process = new MyLoop().execute().get();
        } catch (ExecutionException | InterruptedException e) {
            e.printStackTrace();
        }

        if (process) {
            Intent killswitch = new Intent("end-of-process");
            Log.i("Finish", "Service");
            LocalBroadcastManager.getInstance(this).sendBroadcast(killswitch);
        }
        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private class MyLoop extends AsyncTask<Void, String, Boolean> {

        @Override
        protected Boolean doInBackground(Void... voids) {

            for (int i = 0; i < 10; i++) {
                publishProgress("i = " + i);
                SystemClock.sleep(1000);
            }
            return true;
        }

        @Override
        protected void onProgressUpdate(String... values) {
            String value = values[0];
            Log.i("Foreground Service", value);
        }
    }

}

Logcat output

02/25 17:41:41: Launching 'app' on  Google.
$ adb shell am start -n "example.myapplication/example.myapplication.firstActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Waiting for process to come online...
Connected to process 5060 on device '-google-192.168.42.106:5555'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
I/Zygote: seccomp disabled by setenforce 0
I/e.myapplicatio: Late-enabling -Xcheck:jni
W/e.myapplicatio: Unexpected CPU variant for X86 using defaults: x86
D/libEGL: Emulator has host GPU support, qemu.gles is set to 1.
I/example.myapplication: type=1400 audit(0.0:1122): avc: denied { write } for comm=45474C20496E6974 name="property_service" dev="tmpfs" ino=9335 scontext=u:r:untrusted_app:s0:c96,c256,c512,c768 tcontext=u:object_r:property_socket:s0 tclass=sock_file permissive=1
    type=1400 audit(0.0:1123): avc: denied { connectto } for comm=45474C20496E6974 path="/dev/socket/property_service" scontext=u:r:untrusted_app:s0:c96,c256,c512,c768 tcontext=u:r:init:s0 tclass=unix_stream_socket permissive=1
D/vndksupport: Loading /vendor/lib/egl/libGLES_emulation.so from current namespace instead of sphal namespace.
E/libEGL: load_driver(/vendor/lib/egl/libGLES_emulation.so): dlopen failed: library "/vendor/lib/egl/libGLES_emulation.so" not found
D/vndksupport: Loading /vendor/lib/egl/libEGL_emulation.so from current namespace instead of sphal namespace.
D/libEGL: loaded /vendor/lib/egl/libEGL_emulation.so
D/vndksupport: Loading /vendor/lib/egl/libGLESv1_CM_emulation.so from current namespace instead of sphal namespace.
D/libEGL: loaded /vendor/lib/egl/libGLESv1_CM_emulation.so
D/vndksupport: Loading /vendor/lib/egl/libGLESv2_emulation.so from current namespace instead of sphal namespace.
D/libEGL: loaded /vendor/lib/egl/libGLESv2_emulation.so
W/e.myapplicatio: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (light greylist, reflection)
W/e.myapplicatio: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (light greylist, reflection)
D/OpenGLRenderer: Skia GL Pipeline
D/: HostConnection::get() New Host Connection established 0xe7b6d5c0, tid 5087
I/RenderThread: type=1400 audit(0.0:1124): avc: denied { connectto } for path=006C6F63616C5F6F70656E676C scontext=u:r:untrusted_app:s0:c96,c256,c512,c768 tcontext=u:r:local_opengl:s0 tclass=unix_stream_socket permissive=1
W/: Unrecognized GLES max version string in extensions: 
W/: Process pipe failed
I/ConfigStore: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasWideColorDisplay retrieved: 0
    android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasHDRDisplay retrieved: 0
I/OpenGLRenderer: Initialized EGL, version 1.4
D/OpenGLRenderer: Swap behavior 1
D/EGL_emulation: eglCreateContext: 0xe1fc8e20: maj 2 min 0 rcv 2
D/vndksupport: Loading /vendor/lib/hw/android.hardware.graphics.mapper@2.0-impl.so from current namespace instead of sphal namespace.
D/vndksupport: Loading /vendor/lib/hw/gralloc.vbox86.so from current namespace instead of sphal namespace.
E/EGL_emulation: tid 5087: eglSurfaceAttrib(1354): error 0x3009 (EGL_BAD_MATCH)
W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xe1fc8d60, error=EGL_BAD_MATCH
I/Choreographer: Skipped 31 frames!  The application may be doing too much work on its main thread.
W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@112c025
E/EGL_emulation: tid 5087: eglSurfaceAttrib(1354): error 0x3009 (EGL_BAD_MATCH)
W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xe0846b60, error=EGL_BAD_MATCH
I/Service Running: True
I/Finish: Service
W/ViewRootImpl[thisServiceActivity]: Dropping event due to no window focus: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_BACK, scanCode=0, metaState=0, flags=0x48, repeatCount=0, eventTime=7949110, downTime=7949110, deviceId=-1, source=0x101 }
W/ViewRootImpl[thisServiceActivity]: Cancelling event due to no window focus: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_BACK, scanCode=0, metaState=0, flags=0x68, repeatCount=0, eventTime=7950511, downTime=7949110, deviceId=-1, source=0x101 }
I/Choreographer: Skipped 625 frames!  The application may be doing too much work on its main thread.
I/chatty: uid=10096(example.myapplication) identical 7 lines
W/ViewRootImpl[thisServiceActivity]: Cancelling event due to no window focus: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_BACK, scanCode=0, metaState=0, flags=0x68, repeatCount=0, eventTime=7950511, downTime=7949110, deviceId=-1, source=0x101 }
I/OpenGLRenderer: Davey! duration=10603ms; Flags=0, IntendedVsync=7941734767100, Vsync=7952151433350, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=7952160308707, AnimationStart=7952160414256, PerformTraversalsStart=7952161151710, DrawStart=7952165102838, SyncQueued=7952174190092, SyncStart=7952180127743, IssueDrawCommandsStart=7952180180543, SwapBuffers=7952293099225, FrameCompleted=7952343853615, DequeueBufferDuration=63000, QueueBufferDuration=161000, 
I/Foreground Service: i = 0
    i = 1
I/Foreground Service: i = 2
    i = 3
I/OpenGLRenderer: Davey! duration=10618ms; Flags=0, IntendedVsync=7941734767100, Vsync=7952151433350, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=7952160308707, AnimationStart=7952160414256, PerformTraversalsStart=7952161151710, DrawStart=7952344526709, SyncQueued=7952345327938, SyncStart=7952355852722, IssueDrawCommandsStart=7952355900616, SwapBuffers=7952356170648, FrameCompleted=7952363877516, DequeueBufferDuration=148000, QueueBufferDuration=246000, 
I/Foreground Service: i = 4
I/Foreground Service: i = 5
    i = 6
    i = 7
    i = 8
I/Foreground Service: i = 9
I/onReceive: Received
Process 5060 terminated.

You're blocking the UI thread for 10 seconds by waiting for the result of your AsyncTask:

process = new MyLoop().execute().get();

The Javadoc for get() states:

Waits if necessary for the computation to complete, and then retrieves its result.

This is eliminating any advantage to running it on a background thread and causing your app to freeze. If you need to do something with the result, you should do it in AsyncTask.onPostExecute .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM