A while ago, I tried setting up the Flutter environment and had a brief experience with it. After a long break, I recently became interested again and wanted to see what changes Flutter has undergone.
I followed the official tutorial to set up the Flutter environment and ran flutter doctor without any issues.
I downloaded a demo app project and tried running it on iOS. After the compilation completed, the app was installed on the simulator, but it got stuck on a white screen.
After killing the app, I manually opened it, and it worked fine.
Attempts and Solutions:
I tried installing it on an Android emulator, but encountered the same issue ❌.
I attempted to run flutter clean to clear the cache, but the problem persisted ❌.
I tried running flutter pub cache clean to clear the dependency cache, but the problem remained ❌.
Running flutter run -v to view the output, I noticed that it got stuck at the line Connecting to service protocol:http://127.0.0.1:57071/0dqLN-ZPpFk=/. I suspected an issue with port 57071, so I ran lsof -i:57071 to check the process ID occupying that port and then killed the process using kill <pid>. However, the issue persisted, and I realized that the service changed ports every time, so the problem wasn’t related to that ❌.
Suddenly, I noticed that every time I ran a Flutter command, the first line was Flutter assets will be downloaded from https://storage.flutter-io.cn. Make sure you trust this source!. I remembered that I had changed the source due to a poor network environment in the past. Could it be an issue with this source? I quickly checked the ~/.zshrc file and found the following configuration:
I deleted these lines, restarted VSCode, and ran the command again. The problem was resolved. In retrospect, it seems that the content of this source was outdated or incorrect! ✅
In summary, one should not easily trust third-party sources. Configuring the network environment correctly is always the first step in setting up the environment.
After searching on Stack Overflow for a while, I couldn’t find any answers pointing to the source. I’m documenting this experience here, hoping it can help others facing the same issue. ♥️
If the above solution doesn’t resolve your problem, you can refer to:
运行flutter run -v查看输出信息,发现最后是卡在Connecting to service protocol:http://127.0.0.1:57071/0dqLN-ZPpFk=/这一行了,怀疑是57071这个端口有问题,运行lsof -i:57071查看占用这个端口的进程的pid,然后运行kill <pid>杀掉这个进程。再次运行发现还是不行,并且发现这个service每次都会换个端口,问题应该不是在这。❌
忽然留意到每次运行flutter命令的时候,第一句都是Flutter assets will be downloaded from https://storage.flutter-io.cn. Make sure you trust this source!,想起来以前因为网络环境不好,换过源,不会是这个源有问题吧,于是赶紧查看~/.zshrc文件,果然在里面发现了这个配置
# Rebase d01f70f39..5efe76189 onto d01f70f39 (4 commands) # # Commands: # p, pick <commit> = use commit # r, reword <commit> = use commit, but edit the commit message # e, edit <commit> = use commit, but stop for amending # s, squash <commit> = use commit, but meld into previous commit # f, fixup <commit> = like "squash", but discard this commit's log message # x, exec <command> = run command (the rest of the line) using shell # d, drop <commit> = remove commit # l, label <label> = label current HEAD with a name # t, reset <label> = reset HEAD to a label # m, merge [-C <commit> | -c <commit>] <label> [# <oneline>] # . create a merge commit using the original merge commit's # . message (or the oneline, if no original merge commit was # . specified). Use -c <commit> to reword the commit message. # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted.
In case ORIG_HEAD is no longer useful, you can also use the branchName@{n} syntax, where n is the nth prior position of the branch pointer. So for example, if you rebase featureA branch onto your master branch, but you don’t like the result of the rebase, then you can simply do git reset --hard featureA@{1} to reset the branch back to exactly where it was before you did the rebase. You can read more about the branch@{n} syntax at the official Git docs for revisions.
java.lang.RuntimeException: Unable to instantiate application com.tencent.sigma.patch.HotPatchApplication: java.lang.ClassNotFoundException: Didn't find class "com.tencent.sigma.patch.HotPatchApplication" on path: DexPathList[[zip file "/data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/base.apk"],nativeLibraryDirectories=[/data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/lib/arm, /data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/base.apk!/lib/armeabi, /system/lib, /vendor/lib]] at android.app.LoadedApk.makeApplication(LoadedApk.java:993) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5801) at android.app.ActivityThread.-wrap1(Unknown Source:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1683) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:173) at android.app.ActivityThread.main(ActivityThread.java:6650) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:818) Caused by: java.lang.ClassNotFoundException: Didn't find class "com.tencent.sigma.patch.HotPatchApplication" on path: DexPathList[[zip file "/data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/base.apk"],nativeLibraryDirectories=[/data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/lib/arm, /data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/base.apk!/lib/armeabi, /system/lib, /vendor/lib]] at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:125) at java.lang.ClassLoader.loadClass(ClassLoader.java:379) at java.lang.ClassLoader.loadClass(ClassLoader.java:312) at android.app.Instrumentation.newApplication(Instrumentation.java:1088) at android.app.LoadedApk.makeApplication(LoadedApk.java:987) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5801) at android.app.ActivityThread.-wrap1(Unknown Source:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1683) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:173) at android.app.ActivityThread.main(ActivityThread.java:6650) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:818) Suppressed: java.io.IOException: Failed to open dex files from /data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/base.apk because: Failure to verify dex file '/data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/base.apk': Out-of-order annotation_element name_idx: 7150 then 7150 at dalvik.system.DexFile.openDexFileNative(Native Method) at dalvik.system.DexFile.openDexFile(DexFile.java:353) at dalvik.system.DexFile.<init>(DexFile.java:100) at dalvik.system.DexFile.<init>(DexFile.java:74) at dalvik.system.DexPathList.loadDexFile(DexPathList.java:374) at dalvik.system.DexPathList.makeDexElements(DexPathList.java:337) at dalvik.system.DexPathList.<init>(DexPathList.java:157) at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:65) at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:64) at com.android.internal.os.ClassLoaderFactory.createClassLoader(ClassLoaderFactory.java:73) at com.android.internal.os.ClassLoaderFactory.createClassLoader(ClassLoaderFactory.java:88) at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:69) at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:35) at android.app.LoadedApk.createOrUpdateClassLoaderLocked(LoadedApk.java:695) at android.app.LoadedApk.getClassLoader(LoadedApk.java:729) at android.app.LoadedApk.getResources(LoadedApk.java:956) at android.app.ContextImpl.createAppContext(ContextImpl.java:2282) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5723) ... 8 more
乍一看,以为是HotPatchApplication被混淆的原因导致Class Not Found,于是尝试keep住HotPatchApplication这个类,但是发现问题依旧。于是又怀疑是前不久升级gradle对分包造成了影响,对apk中的dex文件进行分析,发现HotPatchApplication这个类稳稳的躺在第一个dex文件中。
Suppressed: java.io.IOException: Failed to open dex files from /data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/base.apk because: Failure to verify dex file '/data/app/com.tencent.dreamreader-P2-qUIVdDrdEOhONvRwOtw==/base.apk': Out-of-order annotation_element name_idx: 7150 then 7150
-overloadaggressively
Specifies to apply aggressive overloading while obfuscating. Multiple fields and methods can then get the same names, as long as their arguments and return types are different, as required by Java bytecode (not just their arguments, as required by the Java language). This option can make the processed code even smaller (and less comprehensible). Only applicable when obfuscating.
So internally RemoteViews is simply a set of actions that are
“serialized” and sent to another process. Each time you make a call
to something like setDouble(), you’re adding an additional action to
RemoteViews’ internal list.
Because there isn’t a way of clearing these actions from a RemoteViews
object, all of your successive setImageViewBitmap() calls, along with
their Bitmaps, remain in the internal list, and are actually
“serialized” and applied each time your send it. :(
In this case it’s best to just create a new RemoteViews object every time.
/** * Return the number of views available. */ publicabstractintgetCount();
/** * Create the page for the given position. The adapter is responsible * for adding the view to the container given here, although it only * must ensure this is done by the time it returns from * {@link #finishUpdate(ViewGroup)}. * * @param container The containing View in which the page will be shown. * @param position The page position to be instantiated. * @return Returns an Object representing the new page. This does not * need to be a View, but can be some other container of the page. */ public Object instantiateItem(ViewGroup container, int position) { return instantiateItem((View) container, position); }
if (mCurItem == ii.position) { // Keep the current item in the valid range newCurrItem = Math.max(0, Math.min(mCurItem, adapterCount - 1)); needPopulate = true; } continue; }
/** * Called when the host view is attempting to determine if an item's position * has changed. Returns {@link #POSITION_UNCHANGED} if the position of the given * item has not changed or {@link #POSITION_NONE} if the item is no longer present * in the adapter. * * <p>The default implementation assumes that items will never * change position and always returns {@link #POSITION_UNCHANGED}. * * @param object Object representing an item, previously returned by a call to * {@link #instantiateItem(View, int)}. * @return object's new position index from [0, {@link #getCount()}), * {@link #POSITION_UNCHANGED} if the object's position has not changed, * or {@link #POSITION_NONE} if the item is no longer present. */ publicintgetItemPosition(Object object) { return POSITION_UNCHANGED; }