- Методы лечения различных ошибок в Android Studio при разработке проекта
- cannot use ‘@try’ with Objective-C exceptions disabled #87
- Comments
- dmeinrath commented Jul 17, 2017
- dmeinrath commented Jul 17, 2017
- antonargunov commented Jul 18, 2017
- antonargunov commented Jul 21, 2017
- dustinkerstein commented Aug 22, 2017
- dmeinrath commented Sep 22, 2017
- antonargunov commented Sep 30, 2017
- shirkan commented Nov 13, 2017
- abelevtsov commented Mar 24, 2018
- csalmi-branch commented Jan 17, 2019
- fahall commented Jan 23, 2019 •
- fahall commented Jan 24, 2019
- antonargunov commented Jan 24, 2019
- tommygwu commented Jan 25, 2019
- antonargunov commented Jan 29, 2019
- Try-catch v/s Null-check in Android.
- What we know about Try-catch ?
- Performance :
- Moral ?
- Exceptions in coroutines
- Cancellation and Exceptions in coroutines (Part 3) — Gotta catch ’em all!
- Coroutines: First things first
- Cancellation and Exceptions in Coroutines (Part 1)
- A coroutine suddenly failed! What now? 😱
- SupervisorJob to the rescue
- Job or SupervisorJob? 🤔
- Watch out quiz! Who’s my parent? 🎯
- Under the hood
- Dealing with Exceptions 👩🚒
- Launch
- Async
- CoroutineExceptionHandler
Методы лечения различных ошибок в Android Studio при разработке проекта
Сегодня хотел бы поделиться своим анализом и способами лечением разных ошибок при разработке своего продукта в Android Studio. Лично я, не раз сталкивался с различными проблемами и ошибками при компиляции и/или тестировании мобильного приложения. Данный процесс, всегда однообразный и в 99% случаев и всегда нужно тратить n-колличество времени на его устранение. Даже, когда ты уже сталкивался с данной проблемой, ты все равно идешь в поисковик и вспоминаешь, как же решить ту или иную ситуацию.
Я для себя завел файлик, в котором отметил самые частые ошибки — потратив на это несколько часов и перечислил самые популярные ошибки (в дальнейшем планирую просто их запомнить), чтоб сократить свое время в дальнейшем.
Итак, начну по порядку с самой распространенной проблемы и дальше буду перечислять их по мере появления:
1) Если подчеркивает красным код, где используются ресурсы: R. — попробовать (но вероятно не поможет): Build -> Clean Project.
В принципе на Build -> Clean Project можно не терять времени, а лучше всего — слева переключиться на Project, открыть каталог .idea, затем каталог libraries и из него удалить все содержимое. Затем нажать кнопку Sync Project. А затем (если все еще красное, но скорее всего уже будет все ок ) Build -> Clean Project.
2) После внезапного выключения компьютера, после перезапуска может быть во всех проектах весь код красным. Перед этим может быть ошибка: Unable to create Debug Bridge: Unable to start adb server: Unable to obtain result of ‘adb version’. Есть три решения — первое помогло, второе нет (но может быть для другого случая), а третье — не пробовал:
а) File — Invalidate Caches/Restart — Invalidate and Restart
б) Закрыть студию. В корне папки проекта удалить файл(ы) .iml и папку .idea. Вновь запустить студию и импортировать проект.
в) Нажать Ctrl-Alt-O и запустить оптимизацию импорта.
Кстати, adb сервер можно проверить на версию (и работоспособность) и затем перезапустить:
3) Если Android Studio выдает приблизительно такую ошибку: Error:Execution failed for task ‘:app:dexDebug’.
Надо слева переключиться на опцию Project, найти и удалить папку build которая лежит в папке app, т.е. по пути app/build. Затем перестроить весь проект заново: Build -> Rebuild Project.
Такое же решение если ошибка типа: «не могу удалить (создать) папку или файл» и указан путь, который в ведет в app/build. Тоже удаляем папку build и ребилдим проект.
4) В сообщении об ошибке упоминается heap — виртуальная память. А ошибка обычно вызвана ее нехваткой, т.е. невозможностью получить запрашиваемый объем. Поэтому этот запрашиваемый объем надо уменьшить, т.е. переписать дефолтное значение (обычно 2048 MB которое можно изменить в настройках), на меньшее 1024 MB.
В файле проекта gradle.properties пишем:
5) Android Studio пришет примерно такую ошибку: Plugin is too old, please update to a more recent version, or set ANDROID_DAILY_OVERRIDE environment variable to «83648b99316049d63656d7276cb19cc7e95d70a5»
Возможные причины (кроме необходимости регулярного обновления SDK):
а) Загруженный проект был скомпилирован с помощью уже несовместимого старого gradle плагина. В этом случае надо найти и подключить в своем build.gradle проекта этот более старый плагин. т.е. попробовать более старые версии, например: 1.1.3 (часто именно 1.1.x и подходит).
Найти все версии можно здесь.
б) Если в build.gradle проекта используется beta-версия плагина — это означает, что срок ее истек. Посмотреть последние релизы (продакшн и бета) можно также здесь:
6) Иногда при подключении сторонних библиотек могут дублироваться некоторые файлы (обычно связанные с лицензированием). В сообщении будет что-то содержащее слова: duplicate files. Решение — надо посмотреть в сообщении об ошибке или в документации подключенной сторонней библиотеки — какие именно файлы стали избыточными, и перечислить их в build.gradle модуля для исключения (exclude) из билда.
Это делается в директиве packagingOptions (которая, в свою очередь, находится в директиве android).
Источник
cannot use ‘@try’ with Objective-C exceptions disabled #87
Comments
dmeinrath commented Jul 17, 2017
Xcode builds are now dying with this error:
Builds/iOS/Libraries/Plugins/Branch/iOS/Branch-SDK/Requests/BranchInstallRequest.m:43:9: �[31mcannot use ‘@Try’ with Objective-C exceptions disabled�[0m
�[33m>�[0m �[39;1mCompiling�[0m NSMutableDictionary+Branch.m
The text was updated successfully, but these errors were encountered:
dmeinrath commented Jul 17, 2017
using XCode 8.3.3 + Unity 5.6.2
antonargunov commented Jul 18, 2017
antonargunov commented Jul 21, 2017
@dmeinrath I can’t reproduce that issue in our TestBed.
Try to enable Objective-C Exceptions in xcode project.
dustinkerstein commented Aug 22, 2017
I’ve seen this happen a few times, but haven’t figured out how to really isolate it. Seems a bit fluky. Using XCode 8.3.2 and Unity 2017.1.0f3
dmeinrath commented Sep 22, 2017
@antonargunov we have, the worst part is that it seems random when the @Try error occurs.
antonargunov commented Sep 30, 2017
Unity3d doesn’t add several properties into .xcodeproj for PBXNativeTarget «Unity-iPhone» and for PBXProject «Unity-iPhone» and xcode use default values for that properties.
You should set that properties with «YES» in xcode in tab «Build Settings»:
- Apple LLVM 9.0 — Language — Objective C (Enable Objective-C Exceptions)
- Apple LLVM 9.0 — Language — Modules (Enable Modules C and Objective C)
shirkan commented Nov 13, 2017
Facing this issue also with Unity Cloud Build.
Branch SDK 0.3.25, Unity 2017.2.0f3, XCode 9.
In Unity cloud build you cannot change this properties manually, but I see they are being set in BranchPostProcessBuild.cs.
Can you please suggest a different solution?
Thanks.
abelevtsov commented Mar 24, 2018
You can try to use something like this stupid and simple (works for me):
csalmi-branch commented Jan 17, 2019
@dmeinrath are you still experiencing this issue, or did the above workaround help resolve the problem?
fahall commented Jan 23, 2019 •
This still seems to be an issue when using Unity Cloud Build. I get the error listed above using 0.5.4 w/ Unity Cloud Build (tried Unity 2017.2.1f1 & 2017.4.18f1 LTS). I have not tried the workaround yet.
Edit: Not sure what was going wrong. I tried again this afternoon (without the workaround), and everything built fine on 2017.2.1f1 on Unity Cloud Build. I performed one successful build on each of XCode versions 9.0, 9.4, and 10.1.
fahall commented Jan 24, 2019
Okay, here is a bit more information:
- I can compile w/ Cloud Build just fine w/ 2017.2.1f1.
- I cannot compile w/ Cloud Build using Unity 2017.4.18fi. I get the following error:
Libraries/Plugins/Branch/iOS/Branch-SDK/Branch-SDK/BranchUniversalObject.m:513:9: cannot use ‘@try’ with Objective-C exceptions disabled
I tried using XCode versions 9.0, 9.4, and 10.1. I get the same error in all cases. I also tried Branch versions 0.5.4 and 0.4.5.
Any thoughts on what I can try next?
antonargunov commented Jan 24, 2019
@fahall thanks for report, I will re-check cloud building with our testbed, but I have thoughts unity cloud works wrong with project file in some cases.
tommygwu commented Jan 25, 2019
Would be great to get Branch working with Unity 2017.4.18f LTS because that’s the version Unity is adding long term support for.
antonargunov commented Jan 29, 2019
I used cloud building for empty project with Branch Unity SDK.
Environment:
Unity3d 2017.4.18f1
xcode 10.1
Result = SUCCESS:
1: No Library cache found — ALL assets will be re-imported.
2: [Unity] Initialize engine version: 2017.4.18f1 (a9236f402e28)
.
40: publishing finished successfully.
41: Finished: SUCCESS
Источник
Try-catch v/s Null-check in Android.
I believe most of the productive developers are the lazy ones 🤣 . Most of us uses JSON2POJO , ButterKnife etc. to save time. No doubt , it’s good. But sometimes that laziness can slow down your app.
What we know about Try-catch ?
Once in an Interview with a fresher, I asked about try-catch and got funniest reply —
we put that code in try<> that we are afraid of it might be null or it can cause app crash & we catch error in catch<>.
But we can never catch Errors 😒 . Mostly newbies mistakenly takes Errors & Exceptions as same . Well , We were talking about Try-catch and Null Check.
In practice I see exception often used out of laziness. Instead of properly handling an error condition at the location where it occurs, people find it easier to throw an exception and catch it somewhere downstream, often resulting in spitting out some incomprehensible error message to the user.
Performance :
Clemens Vasters tweets some time ago —
Below we can see what happen when we write →
Exceptions do take extra memory, as well as time, to catch. It is ALWAYS better to test for null if it’s a possible value. Another thing to consider it that it’s simply less code and more readable to do the null test. Usually having try/catch blocks adds essentially no overhead to your code for the normal case, but when the exception is triggered it’s quite expensive.
So what do we learned from above ? In one line —
Exceptions are, as their name implies, to be used only for exceptional conditions, they should never be used for ordinary control flow.
Moral ?
There are thousands cases where your code can go wrong: cannot connect to database, IO Exception, Network error… If you deal with them one by one (like the null check here), it would be too much of a hassle
but, if you know that variable/object can be null or it can cause a NullPointerException so better is to check rather than showing laziness (Ctrl+alt+t+6) 💻 ( try-catch shortcut in Android Studio) 😜
Источник
Exceptions in coroutines
Cancellation and Exceptions in coroutines (Part 3) — Gotta catch ’em all!
We, developers, usually spend a lot of time polishing the happy path of our app. However, it’s equally important to provide a proper user experience whenever things don’t go as expected. On one hand, seeing an application crash is a bad experience for the user; on the other hand, showing the right message to the user when an action didn’t succeed is indispensable.
Handling exceptions properly has a huge impact on how users perceive your application. In this article, we’ll explain how exceptions are propagated in coroutines and how you can always be in control, including the different ways to handle them.
If you prefer video, check out this talk from KotlinConf’19 by Florina Muntenescu and I:
⚠️ In order to follow the rest of the article without any problems, reading and understanding Part 1 of the series is required.
Coroutines: First things first
Cancellation and Exceptions in Coroutines (Part 1)
A coroutine suddenly failed! What now? 😱
When a coroutine fails with an exception, it will propagate said exception up to its parent! Then, the parent will 1) cancel the rest of its children, 2) cancel itself and 3) propagate the exception up to its parent.
The exception will reach the root of the hierarchy and all the coroutines that the CoroutineScope started will get cancelled too.
While propagating an exception can make sense in some cases, there are other cases when that’s undesirable. Imagine a UI-related CoroutineScope that processes user interactions. If a child coroutine throws an exception, the UI scope will be cancelled and the whole UI component will become unresponsive as a cancelled scope cannot start more coroutines.
What if you don’t want that behavior? Alternatively, you can use a different implementation of Job , namely SupervisorJob , in the CoroutineContext of the CoroutineScope that creates these coroutines.
SupervisorJob to the rescue
With a SupervisorJob , the failure of a child doesn’t affect other children. A SupervisorJob won’t cancel itself or the rest of its children. Moreover, SupervisorJob won’t propagate the exception either, and will let the child coroutine handle it.
You can create a CoroutineScope like this val uiScope = CoroutineScope(SupervisorJob()) to not propagate cancellation when a coroutine fails as this image depicts:
If the exception is not handled and the CoroutineContext doesn’t have a CoroutineExceptionHandler (as we’ll see later), it will reach the default thread’s ExceptionHandler . In the JVM, the exception will be logged to console; and in Android, it will make your app crash regardless of the Dispatcher this happens on.
💥 Uncaught exceptions will always be thrown regardless of the kind of Job you use
The same behavior applies to the scope builders coroutineScope and supervisorScope . These will create a sub-scope (with a Job or a SupervisorJob accordingly as a parent) with which you can logically group coroutines (e.g. if you want to do parallel computations or you want them to be or not be affected by each other).
Warning: A SupervisorJob only works as described when it’s part of a scope: either created using supervisorScope or CoroutineScope(SupervisorJob()) .
Job or SupervisorJob? 🤔
When should you use a Job or a SupervisorJob ? Use a SupervisorJob or supervisorScope when you don’t want a failure to cancel the parent and siblings.
In this case, if child#1 fails, neither scope nor child#2 will be cancelled.
In this case, as supervisorScope creates a sub-scope with a SupervisorJob , if child#1 fails, child#2 will not be cancelled. If instead you use a coroutineScope in the implementation, the failure will get propagated and will end up cancelling scope too.
Watch out quiz! Who’s my parent? 🎯
Given the following snippet of code, can you identify what kind of Job child#1 has as a parent?
child#1 ’s parentJob is of type Job ! Hope you got it right! Even though at first impression, you might’ve thought that it can be a SupervisorJob , it is not because a new coroutine always gets assigned a new Job() which in this case overrides the SupervisorJob . SupervisorJob is the parent of the coroutine created with scope.launch ; so literally, SupervisorJob does nothing in that code!
Therefore, if either child#1 or child#2 fails, the failure will reach scope and all work started by that scope will be cancelled.
Remember that a SupervisorJob only works as described when it’s part of a scope: either created using supervisorScope or CoroutineScope(SupervisorJob()) . Passing a SupervisorJob as a parameter of a coroutine builder will not have the desired effect you would’ve thought for cancellation.
Regarding exceptions, if any child throws an exception, that SupervisorJob won’t propagate the exception up in the hierarchy and will let its coroutine handle it.
Under the hood
If you’re curious about how Job works under the hood, check out the implementation of the functions childCancelled and notif y Cancelling in the JobSupport.kt file.
In the SupervisorJob implementation, the childCancelled method just returns false , meaning that it doesn’t propagate cancellation but it doesn’t handle the exception either.
Dealing with Exceptions 👩🚒
Coroutines use the regular Kotlin syntax for handling exceptions: try/catch or built-in helper functions like runCatching (which uses try/catch internally).
We said before that uncaught exceptions will always be thrown. However, different coroutines builders treat exceptions in different ways.
Launch
With launch, exceptions will be thrown as soon as they happen. Therefore, you can wrap the code that can throw exceptions inside a try/catch , like in this example:
With launch, exceptions will be thrown as soon as they happen
Async
When async is used as a root coroutine (coroutines that are a direct child of a CoroutineScope instance or supervisorScope ), exceptions are not thrown automatically, instead, they’re thrown when you call .await() .
To handle exceptions thrown in async whenever it’s a root coroutine, you can wrap the .await() call inside a try/catch :
In this case, notice that calling async will never throw the exception, that’s why it’s not necessary to wrap it as well. await will throw the exception that happened inside the async coroutine.
When async is used as a root coroutine, exceptions are thrown when you call .await
Also, notice that we’re using a supervisorScope to call async and await . As we said before, a SupervisorJob lets the coroutine handle the exception; as opposed to Job that will automatically propagate it up in the hierarchy so the catch block won’t be called:
Furthermore, exceptions that happen in coroutines created by other coroutines will always be propagated regardless of the coroutine builder. For example:
In this case, if async throws an exception, it will get thrown as soon as it happens because the coroutine that is the direct child of the scope is launch . The reason is that async (with a Job in its CoroutineContext ) will automatically propagate the exception up to its parent ( launch ) that will throw the exception.
⚠️ Exceptions thrown in a coroutineScope builder or in coroutines created by other coroutines won’t be caught in a try/catch!
In the SupervisorJob section, we mention the existence of CoroutineExceptionHandler . Let’s dive into it!
CoroutineExceptionHandler
The CoroutineExceptionHandler is an optional element of a CoroutineContext allowing you to handle uncaught exceptions.
Here’s how you can define a CoroutineExceptionHandler , whenever an exception is caught, you have information about the CoroutineContext where the exception happened and the exception itself:
Exceptions will be caught if these requirements are met:
- When ⏰: The exception is thrown by a coroutine that automatically throws exceptions (works with launch , not with async ).
- Where 🌍: If it’s in the CoroutineContext of a CoroutineScope or a root coroutine (direct child of CoroutineScope or a supervisorScope ).
Let’s see some examples using the CoroutineExceptionHandler defined above. In the following example, the exception will be caught by the handler:
In this other case in which the handler is installed in a inner coroutine, it won’t be caught:
The exception isn’t caught because the handler is not installed in the right CoroutineContext . The inner launch will propagate the exception up to the parent as soon as it happens, since the parent doesn’t know anything about the handler, the exception will be thrown.
Dealing with exceptions gracefully in your application is important to have a good user experience, even when things don’t go as expected.
Remember to use SupervisorJob when you want to avoid propagating cancellation when an exception happens, and Job otherwise.
Uncaught exceptions will be propagated, catch them to provide a great UX!
Источник