Nano Hash - криптовалюты, майнинг, программирование

Только для Android 7 и 8 — ClassCastException: LayoutParams нельзя преобразовать в AbsListView $ LayoutParams

У меня очень странная проблема, которую я изучаю. Я не писал исходный код, но я выясняю, почему он внезапно падает. Посмотрев на него, я не вижу причин для краха. Кроме того, он отлично работает на более низких уровнях ОС (например, Android 6); тем не менее, он постоянно падает при запуске в Android 7 и 8. Поначалу также было очень трудно воспроизвести, потому что сбой проявляется только после 6-го индекса ... Первоначально думал, что это могут быть какие-то поврежденные данные, потому что проблема только проявляется у определенных пользователей. Но затем я смог воспроизвести последовательно, как только я увеличил количество элементов в списке. Исключение приведения класса происходит в нашем адаптере списка, когда мы перебираем список объектов лекарств и создаем их список для быстрого обращения к пользователю. Индексы от 0 до 5 не имеют проблем; однако после обработки индексов 6 приложение аварийно завершает работу, когда возвращает View (первоначально переданный convertView). Я прошел через код до 6 лекарств и никогда не видел проблем. При переходе с 6-го индекса (7-е лекарство) он постоянно падает, когда возвращается метод getView(...). И, как я уже говорил, это происходит только тогда, когда код работает на Android 7 и 8. Когда код работает на Android 6 (например), он может обрабатывать более 10 лекарств и более. Даже протестировано с пользователем, у которого было 20. Интересно, сталкивался ли кто-нибудь с этим и / или есть предложения / мысли. Возможно ли что-то изменилось в Android 7 и 8 с ресайклером представления адаптера? Нет смысла в том, что это происходит только тогда, когда список лекарств больше, чем может отобразить экран. Это почти как если бы у переработчика была ошибка в Android 7 и 8...

Вот реализация getView(...):

public View getView(int position, View convertView, ViewGroup parent) {

    Log.i(TAG, position + " | " + convertView);

    ViewHolder holder;

    LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);

    // MedicationItem
    MedicationItem medItem_pos = rowItems.get(position);

    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.med_adjustment_reconciliation_item, parent, false);
        holder = new ViewHolder();
        holder.drugInfo = (TextView) convertView.findViewById(R.id.med_adj_recon_list_item_drug_info_textview);
        holder.drugDosageInfo = (TextView) convertView.findViewById(R.id.med_adj_recon_list_item_drug_dosage_info_textview);

        if (medItem_pos.isTaking()) {
            ((ListView)parent).setItemChecked(position, true);

        } else {
            ((ListView)parent).setItemChecked(position, false);
        }

        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    // Build Drug Info
    StringBuilder sbDrugInfo = new StringBuilder(medItem_pos.getDrug());
    if (StringUtils.isNotEmpty(medItem_pos.getTradeName()))
        sbDrugInfo.append(String.format(" (%s) ", Html.fromHtml(medItem_pos.getTradeName())));
    if (null != medItem_pos.getDose() && medItem_pos.getDose() > 0 && StringUtils.isNotEmpty(medItem_pos.getMedUnit())) {
        MedUnit medUnit = EnumUtils.lookup(MedUnit.class, medItem_pos.getMedUnit());
        sbDrugInfo.append(String.format("%s %s", medItem_pos.getDose(), (null==medUnit?medItem_pos.getMedUnit():medUnit.getLocaleString())));
    }

    // Build Drug Dosage Info
    StringBuilder sbDrugDosageInfo = new StringBuilder();
    sbDrugDosageInfo.append(defineQuantity(medItem_pos.getQuantity(), medItem_pos.getDosageFormUnit()));

    if (StringUtils.isNotBlank(medItem_pos.getFrequency())){
        MedFrequency medFrequency = EnumUtils.lookup(MedFrequency.class, medItem_pos.getFrequency());
        if (null != medFrequency){
            if (sbDrugDosageInfo.length() > 0)
                sbDrugDosageInfo.append(" | ").append(medFrequency.getLocaleString());
            else
                sbDrugDosageInfo.append(medFrequency.getLocaleString());
        }else{
            sbDrugDosageInfo.append(MedFrequency.OTHER.getLocaleString());
        }
    }

    // display drug information
    holder.drugInfo.setText(sbDrugInfo.toString());
    holder.drugDosageInfo.setText(sbDrugDosageInfo.toString());

    return convertView;
}

...
...

private class ViewHolder {
    TextView drugInfo;
    TextView drugDosageInfo;
}

Вот ошибка:

02-20 21:22:11.923 909-7727/? I/ActivityManager: START u0 {cmp=com.some.co/.modules.medadjustment.MedAdjustmentActivity (has extras)} from uid 10246
02-20 21:22:11.926 689-689/? D/QCOM PowerHAL: LAUNCH HINT: ON
02-20 21:22:11.928 689-689/? D/QCOM PowerHAL: Activity launch hint handled
02-20 21:22:11.936 675-2136/? D/audio_hw_primary: out_write: retry previous failed cal level set
02-20 21:22:11.951 21906-21911/? I/zygote: Do partial code cache collection, code=126KB, data=89KB
02-20 21:22:11.952 21906-21911/? I/zygote: After code cache collection, code=124KB, data=88KB
02-20 21:22:11.952 21906-21911/? I/zygote: Increasing code cache capacity to 512KB
02-20 21:22:12.074 21906-21906/? D/AndroidRuntime: Shutting down VM
02-20 21:22:12.074 21906-21906/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.some.co, PID: 21906
    java.lang.ClassCastException: android.widget.LinearLayout$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams
        at android.widget.ListView.removeUnusedFixedViews(ListView.java:1990)
        at android.widget.ListView.layoutChildren(ListView.java:1851)
        at android.widget.AbsListView.onLayout(AbsListView.java:2164)
        at android.view.View.layout(View.java:19659)
        at android.view.ViewGroup.layout(ViewGroup.java:6075)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
        at android.view.View.layout(View.java:19659)
        at android.view.ViewGroup.layout(ViewGroup.java:6075)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19659)
        at android.view.ViewGroup.layout(ViewGroup.java:6075)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
        at android.view.View.layout(View.java:19659)
        at android.view.ViewGroup.layout(ViewGroup.java:6075)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
        at android.view.View.layout(View.java:19659)
        at android.view.ViewGroup.layout(ViewGroup.java:6075)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19659)
        at android.view.ViewGroup.layout(ViewGroup.java:6075)
        at android.support.v7.internal.widget.ActionBarOverlayLayout.onLayout(Unknown Source:68)
        at android.view.View.layout(View.java:19659)
        at android.view.ViewGroup.layout(ViewGroup.java:6075)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19659)
        at android.view.ViewGroup.layout(ViewGroup.java:6075)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
        at android.view.View.layout(View.java:19659)
        at android.view.ViewGroup.layout(ViewGroup.java:6075)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at com.android.internal.policy.DecorView.onLayout(DecorView.java:761)
        at android.view.View.layout(View.java:19659)
        at android.view.ViewGroup.layout(ViewGroup.java:6075)
        at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2496)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2212)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1392)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6752)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
        at android.view.Choreographer.doCallbacks(Choreographer.java:723)
        at android.view.Choreographer.doFrame(Choreographer.java:658)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
        at android.os.Handler.handleCallback(Handler.java:790)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6494)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
02-20 21:22:12.078 21906-21906/? I/zygote: System.exit called, status: 2
02-20 21:22:12.078 21906-21906/? I/AndroidRuntime: VM exiting with result code 2, cleanup skipped.
02-20 21:22:12.097 909-1399/? W/InputDispatcher: channel '643fc74 com.some.co/com.some.co.modules.welcome.MyActivity (server)' ~ Consumer closed input channel or an error occurred.  events=0x9
02-20 21:22:12.097 909-1399/? E/InputDispatcher: channel '643fc74 com.some.co/com.some.co.modules.welcome.MyActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
02-20 21:22:12.098 909-949/? W/zygote64: kill(-21906, 9) failed: No such process
02-20 21:22:12.098 909-1664/? I/ActivityManager: Process com.some.co (pid 21906) has died: fore TOP 

Наконец, вот макет xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/med_adj_recon_list_item_background_frame"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/button_white_with_gray_border"
    android:layout_margin="@dimen/spacing_tiny">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:padding="@dimen/spacing_small"
        android:layout_gravity="center_vertical"
        android:layout_margin="@dimen/spacing_small">
        <TextView
            android:id="@+id/med_adj_recon_list_item_drug_info_textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="@dimen/font_normal"
            android:textColor="@drawable/button_custom_med_adjustment_text_color"/>
        <TextView
            android:id="@+id/med_adj_recon_list_item_drug_dosage_info_textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="@dimen/font_small"
            android:textColor="@drawable/button_custom_med_adjustment_text_color"/>
    </LinearLayout>
    <View
        android:id="@+id/med_adj_recon_list_item_divider"
        android:layout_width="1dp"
        android:layout_height="match_parent"
        android:background="@drawable/color_selector"/>
    <ImageView
        android:id="@+id/med_adj_recon_list_item_image_view"
        android:layout_width="@dimen/icon_width"
        android:layout_height="@dimen/icon_height"
        style="@style/IconImageViewBase"
        android:src="@drawable/tick_selector"/>
</LinearLayout>

Иногда помогает еще одна пара глаз. Очень ценю помощь!

Вот импорт из класса фрагментов, который загружает ListView:

import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.some.co.R;
import com.some.co.fragment.CommonFragment;
import com.some.co.modules.home.cards.CardFragment;
import com.some.co.modules.medadjustment.model.DeclineMedicationReason;
import com.some.co.modules.medadjustment.model.MedicationItem;
import com.some.co.modules.medadjustment.model.TextDrawable;

import java.lang.reflect.Type;
import java.util.List;

Вот зависимости в build.gradle:

final ANDROID_SDK_VERSION = '22.2.1'

dependencies {
    compile "com.android.support:design:$ANDROID_SDK_VERSION"
    compile "com.android.support:appcompat-v7:$ANDROID_SDK_VERSION"
    compile "com.android.support:support-v4:$ANDROID_SDK_VERSION"
    compile "com.android.support:cardview-v7:$ANDROID_SDK_VERSION"
    compile "com.android.support:recyclerview-v7:$ANDROID_SDK_VERSION"
    compile 'com.android.support:multidex:1.0.1'
    // only include the needed dependencies from play-services, 8.4 version above require SDK23.
    compile 'com.google.android.gms:play-services-auth:8.3.0'
    compile 'com.google.android.gms:play-services-base:8.3.0'
    compile 'com.google.android.gms:play-services-gcm:8.3.0'
    compile 'com.google.android.gms:play-services-analytics:8.3.0'
    compile 'com.google.android.gms:play-services-location:8.3.0'
    compile 'org.apache.commons:commons-lang3:3.3.2'
    compile 'org.greenrobot:eventbus:3.0.0'
    compile 'org.greenrobot:greendao-encryption:2.2.2'
    compile 'com.google.code.gson:gson:2.3.1'
    compile 'joda-time:joda-time:2.8.2'
    compile 'org.joda:joda-convert:1.4' // for proguard, b/c we're using joda-time (above)
    // for UI testing
    androidTestCompile 'com.jayway.android.robotium:robotium-solo:4.3.1'
    androidTestCompile 'com.squareup.spoon:spoon-client:1.7.0'
}

Кроме того, для compileSdkVersion и targetSdkVersion установлено значение 22.


  • Не могли бы вы поделиться импортом вашего Fragment, в котором вы показываете список? 06.03.2018
  • Вы добавили верхний или нижний колонтитул View на ListView? Похоже, проблема именно в этом. 07.03.2018
  • Привет Реаз, спасибо за ваш ответ. Я добавил это выше. 07.03.2018
  • Привет Майк, спасибо за ваш ответ; ты был прав! Похоже, это проблема с добавлением представления, которое в нашем случае добавлялось как нижний колонтитул, в ListView. Глядя на код, мы раздуваем макет, содержащий кнопку «Далее», как вид и добавляем его в ListView как нижний колонтитул. Я могу только предположить, что это было сделано для того, чтобы не ограничивать ListView между верхним и нижним колонтитулами. Однажды я прокомментировал mMedListView.addFooterView(mNextButtonView); в нашем классе фрагментов было разрешено исключение класса Cast. Любая идея, почему более низкая версия ОС Android не заботилась об этом? 07.03.2018
  • Я не уверен. Как именно вы надуваете и добавляете эту кнопку? Является ли mNextButtonView корнем View раздутого макета? Или он указывает только на кнопку «Далее» внутри него? (Я предполагаю, что кнопка находится внутри LinearLayout.) В любом случае мне придется просмотреть исходный код. 08.03.2018
  • Привет, Майк, да, mNextButtonView — это корневой вид раздутого макета, добавляемый в качестве нижнего колонтитула. Он определен как переменная представления уровня класса в нашем классе фрагментов и инициализируется в нем методом onViewCreated(...). Вот как это делается: mNextButtonView = ((LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.med_adjustment_reconciliation_footer, (ViewGroup)v, false); 08.03.2018
  • Макет нижнего колонтитула — это всего лишь ‹LindearLayout›, содержащий одну ‹Button›, которая является кнопкой «Далее». После инициализации ListView мы добавили к нему mNextButtonView в качестве нижнего колонтитула со следующим: mMedListView.addFooterView(mNextButtonView);. Чтобы исправить мое исключение приведения класса, я просто переместил ‹Button› под ‹ListView› в макете нашего фрагмента и удалил логику в нашем классе фрагментов, чтобы раздуть макет нижнего колонтитула как собственное представление и добавить его как нижний колонтитул в ListView. создан. Итак, моя проблема теперь решена, просто немного озадачен, почему это работало раньше (Android 6). 08.03.2018
  • Хорошо, я пошел копаться в источнике и нашел причину. В Nougat ListView изменила обработку верхнего/нижнего колонтитула View, и это, в сочетании с особым способом увеличения этого нижнего колонтитула и тем фактом, что он изначально скрыт от экрана, когда список достаточно длинный, заставляет ListView попытаться проверить нижний колонтитул LayoutParams до того, как они будут изменены на правильный тип. На самом деле проблема не в том, что LinearLayout обертывает Button, хотя это, вероятно, и не нужно. Это (ViewGroup)v, переданное в вызове inflate(). Это вызывает нижний колонтитул... 09.03.2018
  • View, чтобы установить LinearLayout.LayoutParams при инфляции, что приводит к этому ClassCastException, когда ListView пытается привести к своему собственному типу LayoutParams, чтобы выполнить вышеупомянутую проверку. Вы можете легко исправить это и вернуться к использованию нижнего колонтитула ListView, если хотите, изменив вызов inflate() на inflate(R.layout.med_adjustment_reconciliation_footer, null). Это действительно то, что нужно было делать все время, поскольку единственное, что делал аргумент ViewGroup, — это диктовать, какой тип LayoutParams использовать, и в любом случае это должно было быть оставлено на усмотрение ListView. 09.03.2018
  • Просматривая мои комментарии здесь, я понимаю, что должен был упомянуть, что вы действительно можете передать ListView вместо (ViewGroup)v. В любом случае, это будет правильный тип LayoutParams, и вы избежите этого ClassCastException. 10.03.2018
  • Спасибо за все подробности, Майк, и за всю вашу помощь! 13.03.2018

Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..