From 706878b1e4926c046c5713d03ca552edb2171255 Mon Sep 17 00:00:00 2001 From: GiuseppeS Date: Mon, 24 Feb 2025 18:35:17 +0100 Subject: [PATCH] Migliorato adapter avantielenco ordini di uscita --- app/build.gradle | 3 + .../MainApplicationModule.java | 8 +- .../view/ExtendedSectionedRecyclerView.java | 18 +- .../ExtendedSectionedRecyclerViewNew.java | 44 +++ .../expansion/view/RecyclerViewProfiler.java | 218 +++++++++++ .../view/SectionedRecyclerViewAdapter.java | 350 ++++++++++++++++++ .../rest/consumers/ArticoloRESTConsumer.java | 15 +- .../rest/consumers/CommessaRESTConsumer.java | 33 +- .../rest/consumers/DepositoRESTConsumer.java | 12 +- .../OrdiniUscitaElencoFragment.java | 195 +++++----- .../OrdiniUscitaElencoViewModel.java | 48 +-- .../OrdiniUscitaElencoFiltroViewModel.java | 4 +- .../ui/OrdiniUscitaElencoAdapter.java | 86 +++-- ...t_main_ordini_uscita__list_group_model.xml | 149 ++++---- ...ragment_main_ordini_uscita__list_model.xml | 6 +- 15 files changed, 932 insertions(+), 257 deletions(-) create mode 100644 app/src/main/java/it/integry/integrywmsnative/core/expansion/view/ExtendedSectionedRecyclerViewNew.java create mode 100644 app/src/main/java/it/integry/integrywmsnative/core/expansion/view/RecyclerViewProfiler.java create mode 100644 app/src/main/java/it/integry/integrywmsnative/core/expansion/view/SectionedRecyclerViewAdapter.java diff --git a/app/build.gradle b/app/build.gradle index 30255e9b..8d6f1b99 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -62,6 +62,9 @@ android { android.buildFeatures.dataBinding true android.buildFeatures.buildConfig true + android.dataBinding.enabledForTests true + android.dataBinding.addKtx true + compileOptions { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 diff --git a/app/src/main/java/it/integry/integrywmsnative/MainApplicationModule.java b/app/src/main/java/it/integry/integrywmsnative/MainApplicationModule.java index 60b404d9..c42eab43 100644 --- a/app/src/main/java/it/integry/integrywmsnative/MainApplicationModule.java +++ b/app/src/main/java/it/integry/integrywmsnative/MainApplicationModule.java @@ -168,14 +168,14 @@ public class MainApplicationModule { @Provides @Singleton - CommessaRESTConsumer provideCommessaRESTConsumer(SystemRESTConsumer systemRESTConsumer) { - return new CommessaRESTConsumer(systemRESTConsumer); + CommessaRESTConsumer provideCommessaRESTConsumer(ExecutorService executorService, SystemRESTConsumer systemRESTConsumer) { + return new CommessaRESTConsumer(executorService, systemRESTConsumer); } @Provides @Singleton - DepositoRESTConsumer provideDepositoRESTConsumer(EntityRESTConsumer entityRESTConsumer, SystemRESTConsumer systemRESTConsumer) { - return new DepositoRESTConsumer(entityRESTConsumer, systemRESTConsumer); + DepositoRESTConsumer provideDepositoRESTConsumer(ExecutorService executorService, SystemRESTConsumer systemRESTConsumer) { + return new DepositoRESTConsumer(executorService, systemRESTConsumer); } @Provides diff --git a/app/src/main/java/it/integry/integrywmsnative/core/expansion/view/ExtendedSectionedRecyclerView.java b/app/src/main/java/it/integry/integrywmsnative/core/expansion/view/ExtendedSectionedRecyclerView.java index da2c4b51..e07b7bff 100644 --- a/app/src/main/java/it/integry/integrywmsnative/core/expansion/view/ExtendedSectionedRecyclerView.java +++ b/app/src/main/java/it/integry/integrywmsnative/core/expansion/view/ExtendedSectionedRecyclerView.java @@ -6,19 +6,28 @@ import androidx.databinding.ObservableArrayList; import androidx.databinding.ObservableList; import androidx.recyclerview.widget.RecyclerView; +import com.zhukic.sectionedrecyclerview.SectionedRecyclerViewAdapter; + +import java.util.ArrayList; + import it.integry.integrywmsnative.core.expansion.OnListGeneralChangedCallback; public abstract class ExtendedSectionedRecyclerView extends SectionedRecyclerViewAdapter { + protected ArrayList mDataset = new ArrayList<>(); private View mEmptyView; public ExtendedSectionedRecyclerView(ObservableArrayList myDataset) { - super(); + mDataset.addAll(myDataset); myDataset.addOnListChangedCallback(new OnListGeneralChangedCallback() { @Override public void onChanged(ObservableList sender) { + mDataset.clear(); + mDataset.addAll(sender); + notifyDataChanged(); + notifyDataSetChanged(); checkIfEmpty(); } }); @@ -32,11 +41,14 @@ public abstract class ExtendedSectionedRecyclerView + extends SectionedRecyclerViewAdapter { + + private View mEmptyView; + + public ExtendedSectionedRecyclerViewNew(ObservableArrayList myDataset) { + super(); + + myDataset.addOnListChangedCallback(new OnListGeneralChangedCallback() { + @Override + public void onChanged(ObservableList sender) { + checkIfEmpty(); + } + }); + + checkIfEmpty(); + } + + public ExtendedSectionedRecyclerViewNew setEmptyView(View emptyView) { + this.mEmptyView = emptyView; + this.checkIfEmpty(); + return this; + } + + + + private void checkIfEmpty() { + if (mEmptyView != null) { + final boolean emptyViewVisible = getItemCount() == 0; + mEmptyView.setVisibility(emptyViewVisible ? View.VISIBLE : View.GONE); + } + } + +} diff --git a/app/src/main/java/it/integry/integrywmsnative/core/expansion/view/RecyclerViewProfiler.java b/app/src/main/java/it/integry/integrywmsnative/core/expansion/view/RecyclerViewProfiler.java new file mode 100644 index 00000000..620942b0 --- /dev/null +++ b/app/src/main/java/it/integry/integrywmsnative/core/expansion/view/RecyclerViewProfiler.java @@ -0,0 +1,218 @@ +package it.integry.integrywmsnative.core.expansion.view; + +import android.os.Handler; +import android.os.Looper; +import android.util.Log; +import android.util.SparseArray; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import java.lang.ref.WeakReference; +import java.util.ArrayDeque; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +public class RecyclerViewProfiler { + private static final String TAG = "RVProfiler"; + private final SparseArray bindingTimes; + private final SparseArray creationTimes; + private final Handler mainHandler; + private WeakReference recyclerViewRef; + private boolean isProfilingEnabled = true; + + // Metriche di performance + private long totalBindingTime = 0; + private long totalCreationTime = 0; + private int bindCount = 0; + private int createCount = 0; + private long firstBindTime = 0; + private final ArrayDeque recentBindTimes; + private static final int MAX_RECENT_TIMES = 50; + + public RecyclerViewProfiler(RecyclerView recyclerView) { + this.recyclerViewRef = new WeakReference<>(recyclerView); + this.bindingTimes = new SparseArray<>(); + this.creationTimes = new SparseArray<>(); + this.mainHandler = new Handler(Looper.getMainLooper()); + this.recentBindTimes = new ArrayDeque<>(); + + setupRecyclerViewCallbacks(); + } + + private void setupRecyclerViewCallbacks() { + RecyclerView recyclerView = recyclerViewRef.get(); + if (recyclerView == null) return; + + recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { + if (newState == RecyclerView.SCROLL_STATE_IDLE) { + logPerformanceMetrics(); + } + } + }); + + // Monitora il pre-layout + recyclerView.addOnLayoutChangeListener((v, left, top, right, bottom, + oldLeft, oldTop, oldRight, oldBottom) -> { + if (firstBindTime == 0) { + mainHandler.postDelayed(this::checkInitialPerformance, 500); + } + }); + } + + public void onPreBind(int position) { + if (!isProfilingEnabled) return; + bindingTimes.put(position, System.nanoTime()); + } + + public void onPostBind(int position) { + if (!isProfilingEnabled) return; + + Long startTime = bindingTimes.get(position); + if (startTime != null) { + long bindTime = System.nanoTime() - startTime; + bindingTimes.remove(position); + + if (firstBindTime == 0) { + firstBindTime = bindTime; + } + + totalBindingTime += bindTime; + bindCount++; + + recentBindTimes.addLast(bindTime); + if (recentBindTimes.size() > MAX_RECENT_TIMES) { + recentBindTimes.removeFirst(); + } + + // Segnala binding lenti + if (bindTime > TimeUnit.MILLISECONDS.toNanos(16)) { // 1 frame + Log.w(TAG, String.format("Slow binding at position %d: %.2fms", + position, bindTime / 1_000_000.0)); + } + } + } + + public void onPreCreate(int viewType) { + if (!isProfilingEnabled) return; + creationTimes.put(viewType, System.nanoTime()); + } + + public void onPostCreate(int viewType) { + if (!isProfilingEnabled) return; + + Long startTime = creationTimes.get(viewType); + if (startTime != null) { + long createTime = System.nanoTime() - startTime; + creationTimes.remove(viewType); + + totalCreationTime += createTime; + createCount++; + + // Segnala creazioni lente + if (createTime > TimeUnit.MILLISECONDS.toNanos(8)) { + Log.w(TAG, String.format("Slow view creation for type %d: %.2fms", + viewType, createTime / 1_000_000.0)); + } + } + } + + private void checkInitialPerformance() { + RecyclerView recyclerView = recyclerViewRef.get(); + if (recyclerView == null) return; + + // Verifica inflazione layout + long avgBindTime = bindCount > 0 ? totalBindingTime / bindCount : 0; + if (avgBindTime > TimeUnit.MILLISECONDS.toNanos(8)) { + Log.w(TAG, String.format("High average binding time: %.2fms. " + + "Consider using AsyncLayoutInflater", avgBindTime / 1_000_000.0)); + } + + // Verifica dimensione view pool + RecyclerView.RecycledViewPool pool = recyclerView.getRecycledViewPool(); + if (pool != null) { + int[] viewTypes = getViewTypes(recyclerView); + for (int type : viewTypes) { + if (pool.getRecycledViewCount(type) == 0) { + Log.w(TAG, "ViewPool empty for type " + type + + ". Consider increasing pool size"); + } + } + } + + // Verifica prefetch + if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) { + LinearLayoutManager lm = (LinearLayoutManager) recyclerView.getLayoutManager(); + if (!lm.isItemPrefetchEnabled()) { + Log.w(TAG, "Item prefetch is disabled. Enable it for better performance"); + } + } + } + + private void logPerformanceMetrics() { + if (!isProfilingEnabled || recentBindTimes.isEmpty()) return; + + // Calcola la varianza dei tempi di binding recenti + double mean = recentBindTimes.stream() + .mapToLong(Long::longValue) + .average() + .orElse(0.0); + + double variance = recentBindTimes.stream() + .mapToDouble(time -> Math.pow(time - mean, 2)) + .average() + .orElse(0.0); + + Log.d(TAG, String.format("Performance metrics:\n" + + "Avg binding time: %.2fms\n" + + "Binding time variance: %.2f\n" + + "View creation rate: %.1f%%", + mean / 1_000_000.0, + variance / 1_000_000.0, + createCount * 100.0 / (bindCount + 1))); + } + + private int[] getViewTypes(RecyclerView recyclerView) { + RecyclerView.Adapter adapter = recyclerView.getAdapter(); + if (adapter == null) return new int[0]; + + Set types = new HashSet<>(); + for (int i = 0; i < adapter.getItemCount(); i++) { + types.add(adapter.getItemViewType(i)); + } + return types.stream().mapToInt(Integer::intValue).toArray(); + } + + public void enableProfiling(boolean enabled) { + isProfilingEnabled = enabled; + if (!enabled) { + bindingTimes.clear(); + creationTimes.clear(); + recentBindTimes.clear(); + } + } + + public String getProfilingStats() { + if (bindCount == 0) return "No data collected yet"; + + return String.format(Locale.US, + "Profiling Statistics:\n" + + "Total bindings: %d\n" + + "Average binding time: %.2fms\n" + + "Total view creations: %d\n" + + "Average creation time: %.2fms\n" + + "First binding time: %.2fms\n" + + "Creation/Binding ratio: %.1f%%", + bindCount, + (totalBindingTime / bindCount) / 1_000_000.0, + createCount, + (totalCreationTime / createCount) / 1_000_000.0, + firstBindTime / 1_000_000.0, + createCount * 100.0 / bindCount); + } +} \ No newline at end of file diff --git a/app/src/main/java/it/integry/integrywmsnative/core/expansion/view/SectionedRecyclerViewAdapter.java b/app/src/main/java/it/integry/integrywmsnative/core/expansion/view/SectionedRecyclerViewAdapter.java new file mode 100644 index 00000000..6b43eb10 --- /dev/null +++ b/app/src/main/java/it/integry/integrywmsnative/core/expansion/view/SectionedRecyclerViewAdapter.java @@ -0,0 +1,350 @@ +package it.integry.integrywmsnative.core.expansion.view; + +import android.util.SparseArray; +import android.util.SparseIntArray; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public abstract class SectionedRecyclerViewAdapter extends RecyclerView.Adapter { + + private RecyclerViewProfiler profiler; + + private static final int TYPE_HEADER = 0; + private static final int TYPE_ITEM = 1; + + // Utilizziamo SparseArray invece di HashMap per migliori performance su Android + private final SparseArray
sectionsByPosition; + private final ArrayList
sections; + + // Cache per le posizioni degli item per evitare ricalcoli frequenti + private final SparseIntArray positionCache; + private int lastCacheUpdateCount; + + // Pool di View per riutilizzo + private final RecyclerView.RecycledViewPool sharedPool; + + // Dimensione massima della cache delle posizioni + private static final int MAX_POSITION_CACHE_SIZE = 2000; + + public SectionedRecyclerViewAdapter() { + this.sections = new ArrayList<>(); + this.sectionsByPosition = new SparseArray<>(); + this.positionCache = new SparseIntArray(MAX_POSITION_CACHE_SIZE); + this.sharedPool = new RecyclerView.RecycledViewPool(); + + // Aumentiamo il pool di ViewHolder per tipo + sharedPool.setMaxRecycledViews(TYPE_HEADER, 50); + sharedPool.setMaxRecycledViews(TYPE_ITEM, 200); + } + + @Override + public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + profiler = new RecyclerViewProfiler(recyclerView); + profiler.enableProfiling(false); + + recyclerView.setRecycledViewPool(sharedPool); + + // Ottimizziamo il layout manager per le prestazioni + if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) { + LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); + layoutManager.setItemPrefetchEnabled(true); + layoutManager.setInitialPrefetchItemCount(50); + } + +// recyclerView.post(() -> { + // Precarica alcuni ViewHolder +// for (int i = 0; i < 25; i++) { +// sharedPool.putRecycledView( +// createViewHolder(recyclerView, TYPE_HEADER)); +// } +// for (int i = 0; i < 50; i++) { +// sharedPool.putRecycledView( +// createViewHolder(recyclerView, TYPE_ITEM)); +// } +// }); + } + + protected static class Section { + private final Object headerData; + private final ArrayList itemsData; + private int globalStartPosition; // Posizione globale di inizio sezione + + public Section(Object headerData, int initialCapacity) { + this.headerData = headerData; + this.itemsData = new ArrayList<>(initialCapacity); + this.globalStartPosition = 0; + } + + public Object getHeaderData() { + return headerData; + } + + public List getItemsData() { + return itemsData; + } + + public void addItem(Object item) { + itemsData.add(item); + } + + public int getItemCount() { + return itemsData.size(); + } + + public void setGlobalStartPosition(int position) { + this.globalStartPosition = position; + } + + public int getGlobalStartPosition() { + return globalStartPosition; + } + } + + // ViewHolder pooling e caching + @Override + public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { + super.onViewRecycled(holder); + // Pulizia custom del ViewHolder se necessario + if (holder instanceof OnRecycleListener) { + ((OnRecycleListener) holder).onRecycle(); + } + } + + // Interfaccia per gestire la pulizia custom dei ViewHolder + public interface OnRecycleListener { + void onRecycle(); + } + + @Override + @NonNull + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + profiler.onPreCreate(viewType); + RecyclerView.ViewHolder holder; + if (viewType == TYPE_HEADER) { + holder = onCreateHeaderViewHolder(parent); + } else { + holder = onCreateItemViewHolder(parent); + } + + // Applichiamo ViewHolder pooling + if (holder.itemView.getLayoutParams() == null) { + holder.itemView.setLayoutParams( + new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + ); + } + + profiler.onPostCreate(viewType); + return holder; + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + profiler.onPreBind(position); + PositionInfo posInfo = getItemPositionInfo(position); + + if (getItemViewType(position) == TYPE_HEADER) { + onBindHeaderViewHolder((H) holder, + sections.get(posInfo.sectionPosition).getHeaderData(), + posInfo.sectionPosition); + } else { + Section section = sections.get(posInfo.sectionPosition); + onBindItemViewHolder((I) holder, + section.getItemsData().get(posInfo.itemPosition), + posInfo.sectionPosition, + posInfo.itemPosition); + } + profiler.onPostBind(position); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List payloads) { + if (payloads.isEmpty()) { + super.onBindViewHolder(holder, position, payloads); + return; + } + + // Supporto per aggiornamenti parziali + if (getItemViewType(position) == TYPE_HEADER) { + onBindHeaderViewHolderPartial((H) holder, position, payloads); + } else { + onBindItemViewHolderPartial((I) holder, position, payloads); + } + } + + // Metodi per gestire aggiornamenti parziali + protected void onBindHeaderViewHolderPartial(H holder, int position, List payloads) { + onBindViewHolder(holder, position); + } + + protected void onBindItemViewHolderPartial(I holder, int position, List payloads) { + onBindViewHolder(holder, position); + } + + @Override + public int getItemCount() { + int count = 0; + for (Section section : sections) { + count += section.getItemCount() + 1; + } + return count; + } + + @Override + public int getItemViewType(int position) { + return isHeader(position) ? TYPE_HEADER : TYPE_ITEM; + } + + // Metodi ottimizzati per la gestione delle sezioni + public void addSection(T headerData, int expectedItems) { + sections.add(new Section(headerData, expectedItems)); + updatePositionCache(); + notifyDataSetChanged(); + } + + public void addItem(int sectionPosition, Object item) { + if (sectionPosition >= 0 && sectionPosition < sections.size()) { + sections.get(sectionPosition).addItem(item); + updatePositionCache(); + // Notifichiamo solo l'inserimento invece di un refresh completo + notifyItemInserted(getGlobalPositionForItem(sectionPosition, + sections.get(sectionPosition).getItemCount() - 1)); + } + } + + public void setSections(List headers, Map> items) { + sections.clear(); + sectionsByPosition.clear(); + + int position = 0; + for (T header : headers) { + List sectionItems = items.get(header); + Section section = new Section(header, sectionItems != null ? sectionItems.size() : 5); + if (sectionItems != null) { + section.getItemsData().addAll(sectionItems); + } + section.setGlobalStartPosition(position); + sections.add(section); + sectionsByPosition.put(position, section); + + position += section.getItemCount() + 1; + } + + updatePositionCache(); + notifyDataSetChanged(); + } + + // Gestione efficiente della cache delle posizioni + private void updatePositionCache() { + if (sections.size() > MAX_POSITION_CACHE_SIZE) { + positionCache.clear(); + return; + } + + int currentPosition = 0; + for (int i = 0; i < sections.size(); i++) { + Section section = sections.get(i); + section.setGlobalStartPosition(currentPosition); + sectionsByPosition.put(currentPosition, section); + currentPosition += section.getItemCount() + 1; + } + + lastCacheUpdateCount = getItemCount(); + } + + private boolean isHeader(int position) { + Section section = sectionsByPosition.get(position); + if (section != null) { + return true; + } + + for (int i = 0; i < sections.size(); i++) { + section = sections.get(i); + if (position == section.getGlobalStartPosition()) { + return true; + } + if (position < section.getGlobalStartPosition() + section.getItemCount() + 1) { + return false; + } + } + return false; + } + + private static class PositionInfo { + final int sectionPosition; + final int itemPosition; + + PositionInfo(int sectionPosition, int itemPosition) { + this.sectionPosition = sectionPosition; + this.itemPosition = itemPosition; + } + } + + private PositionInfo getItemPositionInfo(int position) { + // Controllo cache + int cachedSection = positionCache.get(position, -1); + if (cachedSection != -1 && lastCacheUpdateCount == getItemCount()) { + Section section = sections.get(cachedSection); + int relativePos = position - section.getGlobalStartPosition(); + if (relativePos == 0) { + return new PositionInfo(cachedSection, -1); + } + return new PositionInfo(cachedSection, relativePos - 1); + } + + // Ricerca ottimizzata + Section targetSection = sectionsByPosition.get(position); + if (targetSection != null) { + int sectionIndex = sections.indexOf(targetSection); + return new PositionInfo(sectionIndex, -1); + } + + // Ricerca binaria nelle sezioni + int left = 0; + int right = sections.size() - 1; + + while (left <= right) { + int mid = (left + right) >>> 1; + Section section = sections.get(mid); + int sectionStart = section.getGlobalStartPosition(); + int sectionEnd = sectionStart + section.getItemCount() + 1; + + if (position >= sectionStart && position < sectionEnd) { + int relativePos = position - sectionStart; + if (relativePos == 0) { + return new PositionInfo(mid, -1); + } + return new PositionInfo(mid, relativePos - 1); + } + + if (position < sectionStart) { + right = mid - 1; + } else { + left = mid + 1; + } + } + + throw new IndexOutOfBoundsException("Position " + position + " is out of bounds"); + } + + private int getGlobalPositionForItem(int sectionPosition, int itemPosition) { + return sections.get(sectionPosition).getGlobalStartPosition() + itemPosition + 1; + } + + // Metodi astratti che devono essere implementati + protected abstract H onCreateHeaderViewHolder(ViewGroup parent); + protected abstract I onCreateItemViewHolder(ViewGroup parent); + protected abstract void onBindHeaderViewHolder(H holder, Object headerData, int sectionPosition); + protected abstract void onBindItemViewHolder(I holder, Object itemData, int sectionPosition, int itemPosition); +} \ No newline at end of file diff --git a/app/src/main/java/it/integry/integrywmsnative/core/rest/consumers/ArticoloRESTConsumer.java b/app/src/main/java/it/integry/integrywmsnative/core/rest/consumers/ArticoloRESTConsumer.java index fa024ef8..12bc1577 100644 --- a/app/src/main/java/it/integry/integrywmsnative/core/rest/consumers/ArticoloRESTConsumer.java +++ b/app/src/main/java/it/integry/integrywmsnative/core/rest/consumers/ArticoloRESTConsumer.java @@ -178,7 +178,7 @@ public class ArticoloRESTConsumer extends _BaseRESTConsumer { } - public void getArtsGroups(List groupsToFind, RunnableArgs> onComplete, RunnableArgs onFailed) { + public List getArtsGroupsSynchronized(List groupsToFind) throws Exception { var whereCondMap = Stream.of(groupsToFind) .map(x -> { HashMap vars = new HashMap<>(); @@ -192,7 +192,18 @@ public class ArticoloRESTConsumer extends _BaseRESTConsumer { Type typeOfObjectsList = new TypeToken>() { }.getType(); - this.systemRESTConsumer.processSql("SELECT * FROM mtb_grup " + whereCond, typeOfObjectsList, onComplete, onFailed); + return this.systemRESTConsumer.processSqlSynchronized("SELECT * FROM mtb_grup " + whereCond, typeOfObjectsList); + } + + public void getArtsGroups(List groupsToFind, RunnableArgs> onComplete, RunnableArgs onFailed) { + executorService.execute(() -> { + try { + var data = getArtsGroupsSynchronized(groupsToFind); + if (onComplete != null) onComplete.run(data); + } catch (Exception ex) { + if (onFailed != null) onFailed.run(ex); + } + }); } diff --git a/app/src/main/java/it/integry/integrywmsnative/core/rest/consumers/CommessaRESTConsumer.java b/app/src/main/java/it/integry/integrywmsnative/core/rest/consumers/CommessaRESTConsumer.java index 2397e97e..9393c916 100644 --- a/app/src/main/java/it/integry/integrywmsnative/core/rest/consumers/CommessaRESTConsumer.java +++ b/app/src/main/java/it/integry/integrywmsnative/core/rest/consumers/CommessaRESTConsumer.java @@ -6,6 +6,7 @@ import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.concurrent.ExecutorService; import java.util.stream.Collectors; import javax.inject.Singleton; @@ -18,34 +19,42 @@ import it.integry.integrywmsnative.core.utility.UtilityString; @Singleton public class CommessaRESTConsumer extends _BaseRESTConsumer { + private final ExecutorService executorService; private final SystemRESTConsumer systemRESTConsumer; - public CommessaRESTConsumer(SystemRESTConsumer systemRESTConsumer) { + public CommessaRESTConsumer(ExecutorService executorService, SystemRESTConsumer systemRESTConsumer) { + this.executorService = executorService; this.systemRESTConsumer = systemRESTConsumer; } - public void getJtbComts(List itemsToFind, RunnableArgs> onComplete, RunnableArgs onFailed) { - var whereCondMap = itemsToFind.stream() + public List getJtbComtsSynchronized(List itemsToFind) throws Exception { + List> whereCondMap = itemsToFind.stream() .filter(x -> !UtilityString.isNullOrEmpty(x)) - .map(x -> { - HashMap codJcom = new HashMap<>() {{ - put("cod_jcom", x); - }}; - return codJcom; - }) + .map(x -> new HashMap() {{ + put("cod_jcom", x); + }}) .collect(Collectors.toUnmodifiableList()); if(whereCondMap.isEmpty()) { - onComplete.run(new ArrayList<>()); - return; + return new ArrayList<>(); } var whereCond = " WHERE " + UtilityQuery.concatFieldListInWhereCond(whereCondMap); Type typeOfObjectsList = new TypeToken>() {}.getType(); - this.systemRESTConsumer.processSql("SELECT * FROM jtb_comt " + whereCond, typeOfObjectsList, onComplete, onFailed); + return this.systemRESTConsumer.processSqlSynchronized("SELECT * FROM jtb_comt " + whereCond, typeOfObjectsList); + } + public void getJtbComts(List itemsToFind, RunnableArgs> onComplete, RunnableArgs onFailed) { + executorService.execute(() -> { + try { + var data = getJtbComtsSynchronized(itemsToFind); + if (onComplete != null) onComplete.run(data); + } catch (Exception ex) { + if (onFailed != null) onFailed.run(ex); + } + }); } } diff --git a/app/src/main/java/it/integry/integrywmsnative/core/rest/consumers/DepositoRESTConsumer.java b/app/src/main/java/it/integry/integrywmsnative/core/rest/consumers/DepositoRESTConsumer.java index 93853e04..e4df1bfb 100644 --- a/app/src/main/java/it/integry/integrywmsnative/core/rest/consumers/DepositoRESTConsumer.java +++ b/app/src/main/java/it/integry/integrywmsnative/core/rest/consumers/DepositoRESTConsumer.java @@ -5,26 +5,26 @@ import com.google.gson.reflect.TypeToken; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ExecutorService; import javax.inject.Singleton; -import it.integry.integrywmsnative.core.expansion.RunnableArgs; import it.integry.integrywmsnative.core.model.MtbDepo; @Singleton public class DepositoRESTConsumer extends _BaseRESTConsumer { - private final EntityRESTConsumer entityRESTConsumer; + private final ExecutorService executorService; private final SystemRESTConsumer systemRESTConsumer; - public DepositoRESTConsumer(EntityRESTConsumer entityRESTConsumer, SystemRESTConsumer systemRESTConsumer) { - this.entityRESTConsumer = entityRESTConsumer; + public DepositoRESTConsumer(ExecutorService executorService, SystemRESTConsumer systemRESTConsumer) { + this.executorService = executorService; this.systemRESTConsumer = systemRESTConsumer; } - public void getAll(RunnableArgs> onComplete, RunnableArgs onFailed) { + public List getAllSynchronized() throws Exception { Type typeOfObjectsList = new TypeToken>() { }.getType(); - this.systemRESTConsumer.processSql("SELECT * FROM mtb_depo", typeOfObjectsList, onComplete, onFailed); + return this.systemRESTConsumer.processSqlSynchronized("SELECT * FROM mtb_depo", typeOfObjectsList); } } diff --git a/app/src/main/java/it/integry/integrywmsnative/gest/ordini_uscita_elenco/OrdiniUscitaElencoFragment.java b/app/src/main/java/it/integry/integrywmsnative/gest/ordini_uscita_elenco/OrdiniUscitaElencoFragment.java index f60e7674..b145c9df 100644 --- a/app/src/main/java/it/integry/integrywmsnative/gest/ordini_uscita_elenco/OrdiniUscitaElencoFragment.java +++ b/app/src/main/java/it/integry/integrywmsnative/gest/ordini_uscita_elenco/OrdiniUscitaElencoFragment.java @@ -2,6 +2,7 @@ package it.integry.integrywmsnative.gest.ordini_uscita_elenco; import android.content.Context; import android.os.Bundle; +import android.os.Handler; import android.text.Html; import android.view.LayoutInflater; import android.view.View; @@ -93,6 +94,9 @@ public class OrdiniUscitaElencoFragment extends BaseFragment implements ITitledF @Inject OrdiniUscitaElencoViewModel mViewModel; + @Inject + Handler handler; + private final OrdiniUscitaElencoFiltroViewModel mAppliedFilterViewModel = new OrdiniUscitaElencoFiltroViewModel(); private FragmentMainOrdiniUscitaBinding mBindings = null; @@ -107,7 +111,7 @@ public class OrdiniUscitaElencoFragment extends BaseFragment implements ITitledF private ElevatedToolbar mToolbar; private final List mOnPreDestroyList = new ArrayList<>(); - private int barcodeScannerIstanceID = -1; + private int mBarcodeScannerInstanceID = -1; private List mtbDepoCache; private List mtbGrupCache; @@ -175,18 +179,43 @@ public class OrdiniUscitaElencoFragment extends BaseFragment implements ITitledF @Override public void onStart() { super.onStart(); - this.onLoadingStarted(); - this.initMtbDepoCache(() -> { - String codMdep = SettingsManager.i().getUserSession().getDepo().getCodMdep(); - mViewModel.init(codMdep, mCurrentGestioneOrd, mCurrentGestioneCol, mCurrentSegnoCol); + this.mViewModel.getOrderList().observe(getViewLifecycleOwner(), data -> { + executorService.execute(() -> { + try { + this.onLoadingStarted(); + this.initMtbGrupsCache(); + this.initJtbComtCache(); + + + mAppliedFilterViewModel.init(data); + + this.refreshList(data, null); + this.onLoadingEnded(); + } catch (Exception e) { + onError(e); + } + }); }); + this.onLoadingStarted(); + executorService.execute(() -> { + try { + this.initMtbDepoCache(); + + String codMdep = SettingsManager.i().getUserSession().getDepo().getCodMdep(); + mViewModel.init(codMdep, mCurrentGestioneOrd, mCurrentGestioneCol, mCurrentSegnoCol); + + this.onLoadingEnded(); + } catch (Exception e) { + onError(e); + } + }); } @Override public void onDestroy() { - BarcodeManager.removeCallback(barcodeScannerIstanceID); + BarcodeManager.removeCallback(mBarcodeScannerInstanceID); for (Runnable onPreDestroy : mOnPreDestroyList) { onPreDestroy.run(); @@ -198,71 +227,70 @@ public class OrdiniUscitaElencoFragment extends BaseFragment implements ITitledF private void initRecyclerView() { + this.onLoadingStarted(); + + boolean canSelectMultipleOrdini = SettingsManager.iDB().isFlagSpedizioneCanSelectMultipleOrders(); boolean canSelectMultipleClienti = SettingsManager.iDB().isFlagMultiClienteOrdV(); - this.mViewModel.getOrderList().observe(getViewLifecycleOwner(), v -> { - this.onLoadingStarted(); - this.initMtbGrupsCache(() -> { - this.initJtbComtCache(this::onLoadingEnded); - }); + executorService.execute(() -> { - mAppliedFilterViewModel.init(mViewModel.getOrderList().getValue()); - this.refreshList(null); + OrdiniUscitaElencoAdapter ordiniUscitaElencoAdapter = + new OrdiniUscitaElencoAdapter(getActivity(), mOrdiniInevasiMutableData) + .setOnGroupItemClicked(x -> { + if (!canSelectMultipleClienti) { + Stream.of(mOrdiniInevasiMutableData) + .filter(y -> !y.getGroupTitle().equalsIgnoreCase(x) && y.getSelectedObservable().get()) + .forEach(y -> y.getSelectedObservable().set(false)); + } + + boolean allSelected = Stream.of(mOrdiniInevasiMutableData) + .filter(y -> y.getGroupTitle().equalsIgnoreCase(x)) + .allMatch(y -> y.getSelectedObservable().get()); + + Stream.of(mOrdiniInevasiMutableData) + .filter(y -> y.getGroupTitle().equalsIgnoreCase(x)) + .forEach(y -> y.getSelectedObservable().set(!allSelected)); + }) + .setOnItemChecked(x -> { + if (!canSelectMultipleClienti && x.getSelectedObservable().get()) { + Stream.of(mOrdiniInevasiMutableData) + .filter(y -> !y.getGroupTitle().equalsIgnoreCase(x.getGroupTitle()) && y.getSelectedObservable().get()) + .forEach(y -> y.getSelectedObservable().set(false)); + } + + fabVisible.set(Stream.of(mOrdiniInevasiMutableData) + .anyMatch(y -> y.getSelectedObservable().get())); + }); + + ordiniUscitaElencoAdapter + .setEmptyView(this.mBindings.ordiniVenditaEmptyView); + + this.mBindings.venditaMainList.setLayoutManager(new LinearLayoutManager(getActivity())); + this.mBindings.venditaMainList.setItemViewCacheSize(20); + this.mBindings.venditaMainList.setAdapter(ordiniUscitaElencoAdapter); + }); - - OrdiniUscitaElencoAdapter ordiniUscitaElencoAdapter = - new OrdiniUscitaElencoAdapter(getActivity(), mOrdiniInevasiMutableData) - .setOnGroupItemClicked(x -> { - if (!canSelectMultipleClienti) { - Stream.of(mOrdiniInevasiMutableData) - .filter(y -> !y.getGroupTitle().equalsIgnoreCase(x) && y.getSelectedObservable().get()) - .forEach(y -> y.getSelectedObservable().set(false)); - } - - boolean allSelected = Stream.of(mOrdiniInevasiMutableData) - .filter(y -> y.getGroupTitle().equalsIgnoreCase(x)) - .allMatch(y -> y.getSelectedObservable().get()); - - Stream.of(mOrdiniInevasiMutableData) - .filter(y -> y.getGroupTitle().equalsIgnoreCase(x)) - .forEach(y -> y.getSelectedObservable().set(!allSelected)); - }) - .setOnItemChecked(x -> { - if (!canSelectMultipleClienti && x.getSelectedObservable().get()) { - Stream.of(mOrdiniInevasiMutableData) - .filter(y -> !y.getGroupTitle().equalsIgnoreCase(x.getGroupTitle()) && y.getSelectedObservable().get()) - .forEach(y -> y.getSelectedObservable().set(false)); - } - - fabVisible.set(Stream.of(mOrdiniInevasiMutableData) - .anyMatch(y -> y.getSelectedObservable().get())); - }); - - ordiniUscitaElencoAdapter - .setEmptyView(this.mBindings.ordiniVenditaEmptyView); - - this.mBindings.venditaMainList.setAdapter(ordiniUscitaElencoAdapter); - this.mBindings.venditaMainList.setLayoutManager(new LinearLayoutManager(getActivity())); + this.onLoadingEnded(); // if (mToolbar != null) // mToolbar.setRecyclerView(this.mBindings.venditaMainList); } private void initBarcodeReader() { - barcodeScannerIstanceID = BarcodeManager.addCallback(new BarcodeCallbackDTO() + mBarcodeScannerInstanceID = BarcodeManager.addCallback(new BarcodeCallbackDTO() .setOnScanSuccessful(onScanSuccessful) .setOnScanFailed(ex -> UtilityExceptions.defaultException(getActivity(), ex, false))); - BarcodeManager.enable(); + BarcodeManager.enable(mBarcodeScannerInstanceID); } private void initFilters() { var onPredicateChanged = new OnGeneralChangedCallback() { @Override public void run() { - refreshList(null); + refreshList(mViewModel.getOrderList().getValue(), null); } }; @@ -714,21 +742,21 @@ public class OrdiniUscitaElencoFragment extends BaseFragment implements ITitledF this.mViewModel.processBarcodeDTO(data, this::onLoadingEnded); }; - private void refreshList(List filteredList) { - requireActivity().runOnUiThread(() -> { - List tmpList; + private void refreshList(List originalData, List filteredList) { + List tmpList; - if (filteredList != null) { - tmpList = filteredList; - } else if (mAppliedFilterViewModel != null) { - mAppliedFilterViewModel.applyAllTests(); - tmpList = mAppliedFilterViewModel.getMutableFilteredOrderList().getValue(); - } else { - tmpList = mViewModel.getOrderList().getValue(); - } + if (filteredList != null) { + tmpList = filteredList; + } else if (mAppliedFilterViewModel != null) { + mAppliedFilterViewModel.applyAllTests(); + tmpList = mAppliedFilterViewModel.getMutableFilteredOrderList().getValue(); + } else { + tmpList = originalData; + } - var list = convertDataModelToListModel(tmpList); + var list = convertDataModelToListModel(tmpList); + handler.post(() -> { this.mOrdiniInevasiMutableData.clear(); this.mOrdiniInevasiMutableData.addAll(list); @@ -744,7 +772,7 @@ public class OrdiniUscitaElencoFragment extends BaseFragment implements ITitledF .thenComparing(ComparatorCompat.comparing(x -> x.getDestinatario() != null ? x.getDestinatario() : "zzzzzzzzz")) .thenComparing(ComparatorCompat.comparing(OrdiniUscitaElencoDTO::getNumOrd)); - List notHiddenElements = Stream.of(dataList) + List notHiddenElements = dataList.parallelStream() .filter(x -> !x.isHidden()) .sorted(comparator) .map(x -> { @@ -774,7 +802,7 @@ public class OrdiniUscitaElencoFragment extends BaseFragment implements ITitledF return listModel; }) - .toList(); + .collect(Collectors.toList()); return notHiddenElements; } @@ -814,7 +842,7 @@ public class OrdiniUscitaElencoFragment extends BaseFragment implements ITitledF @Override public void onOrderFiltered(List filteredOrders) { - refreshList(filteredOrders); + refreshList(mViewModel.getOrderList().getValue(), filteredOrders); } @Override @@ -874,38 +902,34 @@ public class OrdiniUscitaElencoFragment extends BaseFragment implements ITitledF } - private void initMtbDepoCache(Runnable onComplete) { - this.mDepositoRESTConsumer.getAll(mtbDepos -> { - this.mtbDepoCache = mtbDepos; - onComplete.run(); - }, this::onError); + private void initMtbDepoCache() throws Exception { + var mtbDepos = this.mDepositoRESTConsumer.getAllSynchronized(); + this.mtbDepoCache = mtbDepos; } - private void initMtbGrupsCache(Runnable onComplete) { - var codMgrpArts = Stream.of(Objects.requireNonNull(this.mViewModel.getOrderList().getValue())) - .flatMap(x -> Stream.of(x.getAvailableClassMerc() != null ? x.getAvailableClassMerc() : new ArrayList<>())) + private void initMtbGrupsCache() throws Exception { + var codMgrpArts = Objects.requireNonNull(this.mViewModel.getOrderList().getValue()).parallelStream() + .filter(x -> x.getAvailableClassMerc() != null && !x.getAvailableClassMerc().isEmpty()) + .flatMap(x -> x.getAvailableClassMerc().stream()) .map(OrdineUscitaInevasoDTO.AvailableClassMerc::getCodMgrp) - .withoutNulls() + .filter(Objects::nonNull) .distinct() - .toList(); + .collect(Collectors.toList()); - this.mArticoloRESTConsumer.getArtsGroups(codMgrpArts, mtbGrupCache -> { - this.mtbGrupCache = mtbGrupCache; - onComplete.run(); - }, this::onError); + var mtbGrupCache = this.mArticoloRESTConsumer.getArtsGroupsSynchronized(codMgrpArts); + this.mtbGrupCache = mtbGrupCache; } - private void initJtbComtCache(Runnable onComplete) { + private void initJtbComtCache() throws Exception { if (this.mViewModel.getOrderList().getValue() == null) { this.jtbComtCache = new ArrayList<>(); - onComplete.run(); return; } List jtbComts = null; - if(this.mViewModel.getOrderList().getValue() != null) { + if (this.mViewModel.getOrderList().getValue() != null) { jtbComts = this.mViewModel.getOrderList().getValue().stream() .map(OrdineUscitaInevasoDTO::getCodJcom) .distinct() @@ -915,13 +939,10 @@ public class OrdiniUscitaElencoFragment extends BaseFragment implements ITitledF if (jtbComts == null || jtbComts.isEmpty()) { this.jtbComtCache = new ArrayList<>(); - onComplete.run(); return; } - this.mCommessaRESTConsumer.getJtbComts(jtbComts, jtbComtCache -> { - this.jtbComtCache = jtbComtCache; - onComplete.run(); - }, this::onError); + var jtbComtCache = this.mCommessaRESTConsumer.getJtbComtsSynchronized(jtbComts); + this.jtbComtCache = jtbComtCache; } } diff --git a/app/src/main/java/it/integry/integrywmsnative/gest/ordini_uscita_elenco/OrdiniUscitaElencoViewModel.java b/app/src/main/java/it/integry/integrywmsnative/gest/ordini_uscita_elenco/OrdiniUscitaElencoViewModel.java index b9a491b9..3854c793 100644 --- a/app/src/main/java/it/integry/integrywmsnative/gest/ordini_uscita_elenco/OrdiniUscitaElencoViewModel.java +++ b/app/src/main/java/it/integry/integrywmsnative/gest/ordini_uscita_elenco/OrdiniUscitaElencoViewModel.java @@ -8,6 +8,8 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; import javax.inject.Inject; @@ -57,39 +59,37 @@ public class OrdiniUscitaElencoViewModel { } - public void init(String currentCodMdep, GestioneEnum gestioneOrd, GestioneEnum gestioneCol, int segnoCol) { + public void init(String currentCodMdep, GestioneEnum gestioneOrd, GestioneEnum gestioneCol, int segnoCol) throws Exception { this.mCurrentCodMdep = currentCodMdep; this.mCurrentGestioneOrd = gestioneOrd; this.mCurrentGestioneCol = gestioneCol; this.mCurrentSegnoCol = segnoCol; - this.sendOnLoadingStarted(); +// Date loadingStartDate = new Date(); - Date loadingStartDate = new Date(); + var ordiniLavorazione = this.mOrdiniRESTConsumer.getOrdiniInevasiSynchronized(this.mCurrentCodMdep, mCurrentGestioneOrd); - this.mOrdiniRESTConsumer.getOrdiniInevasi(this.mCurrentCodMdep, mCurrentGestioneOrd, - ordiniLavorazione -> { - this.mOrderList.postValue(Stream.of(ordiniLavorazione) - .map(x -> { - try { - return OrdiniUscitaElencoDTO.fromParent(x); - } catch (Exception ex) { - return null; - } - }) - .toList()); - - long forcedDelaySecs = (new Date().getTime() - loadingStartDate.getTime()) / 1000; - - if (2 - forcedDelaySecs > 0) { - try { - Thread.sleep((2 - forcedDelaySecs) * 1000); - } catch (Exception ignored) { - } + var orderList = ordiniLavorazione.parallelStream() + .map(x -> { + try { + return OrdiniUscitaElencoDTO.fromParent(x); + } catch (Exception ex) { + return null; } + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); - this.sendOnLoadingEnded(); - }, this::sendError); + this.mOrderList.postValue(orderList); + +// long forcedDelaySecs = (new Date().getTime() - loadingStartDate.getTime()) / 1000; +// +// if (2 - forcedDelaySecs > 0) { +// try { +// Thread.sleep((2 - forcedDelaySecs) * 1000); +// } catch (Exception ignored) { +// } +// } } diff --git a/app/src/main/java/it/integry/integrywmsnative/gest/ordini_uscita_elenco/filters/OrdiniUscitaElencoFiltroViewModel.java b/app/src/main/java/it/integry/integrywmsnative/gest/ordini_uscita_elenco/filters/OrdiniUscitaElencoFiltroViewModel.java index 5589489b..9d71487e 100644 --- a/app/src/main/java/it/integry/integrywmsnative/gest/ordini_uscita_elenco/filters/OrdiniUscitaElencoFiltroViewModel.java +++ b/app/src/main/java/it/integry/integrywmsnative/gest/ordini_uscita_elenco/filters/OrdiniUscitaElencoFiltroViewModel.java @@ -44,7 +44,7 @@ public class OrdiniUscitaElencoFiltroViewModel { public void init(List initialList) { this.initialOrderList = initialList; - this.currentFilteredOrderList.setValue(this.initialOrderList); + this.currentFilteredOrderList.postValue(this.initialOrderList); } public MutableLiveData> getMutableFilteredOrderList() { @@ -192,7 +192,7 @@ public class OrdiniUscitaElencoFiltroViewModel { returnList = tmpStream.toList(); } - this.currentFilteredOrderList.setValue(returnList); + this.currentFilteredOrderList.postValue(returnList); } public ObservableField> getCurrentDepositoPredicate() { diff --git a/app/src/main/java/it/integry/integrywmsnative/gest/ordini_uscita_elenco/ui/OrdiniUscitaElencoAdapter.java b/app/src/main/java/it/integry/integrywmsnative/gest/ordini_uscita_elenco/ui/OrdiniUscitaElencoAdapter.java index 9ad20f1d..8c608194 100644 --- a/app/src/main/java/it/integry/integrywmsnative/gest/ordini_uscita_elenco/ui/OrdiniUscitaElencoAdapter.java +++ b/app/src/main/java/it/integry/integrywmsnative/gest/ordini_uscita_elenco/ui/OrdiniUscitaElencoAdapter.java @@ -8,24 +8,34 @@ import android.view.View; import android.view.ViewGroup; import androidx.core.content.res.ResourcesCompat; -import androidx.databinding.DataBindingUtil; import androidx.databinding.ObservableArrayList; +import androidx.databinding.ObservableList; import androidx.recyclerview.widget.RecyclerView; -import it.integry.integrywmsnative.R; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import it.integry.integrywmsnative.core.expansion.OnListGeneralChangedCallback; import it.integry.integrywmsnative.core.expansion.OnSingleClickListener; import it.integry.integrywmsnative.core.expansion.RunnableArgs; -import it.integry.integrywmsnative.core.expansion.view.ExtendedSectionedRecyclerView; +import it.integry.integrywmsnative.core.expansion.view.ExtendedSectionedRecyclerViewNew; import it.integry.integrywmsnative.core.utility.UtilityString; import it.integry.integrywmsnative.databinding.FragmentMainOrdiniUscitaListGroupModelBinding; import it.integry.integrywmsnative.databinding.FragmentMainOrdiniUscitaListModelBinding; -public class OrdiniUscitaElencoAdapter extends ExtendedSectionedRecyclerView { +public class OrdiniUscitaElencoAdapter extends ExtendedSectionedRecyclerViewNew { private final Context mContext; +// private final AsyncLayoutInflater asyncLayoutInflater; + private final LayoutInflater layoutInflater; + private RunnableArgs mOnGroupItemClicked; private RunnableArgs mOnItemChecked; + + static class SubheaderHolder extends RecyclerView.ViewHolder { FragmentMainOrdiniUscitaListModelBinding mBinding; @@ -50,6 +60,22 @@ public class OrdiniUscitaElencoAdapter extends ExtendedSectionedRecyclerView mutableDataSet) { super(mutableDataSet); mContext = context; + layoutInflater = LayoutInflater.from(mContext); +// asyncLayoutInflater = new AsyncLayoutInflater(mContext); + + mutableDataSet.addOnListChangedCallback(new OnListGeneralChangedCallback() { + @Override + public void onChanged(ObservableList sender) { + + Map> collect = sender.stream() + .collect(Collectors.groupingBy(OrdiniUscitaElencoListModel::getGroupTitle)); + + String[] keyArray = new String[collect.keySet().size()]; + collect.keySet().toArray(keyArray); + + setSections(Arrays.asList(keyArray), collect); + } + }); } public OrdiniUscitaElencoAdapter setOnGroupItemClicked(RunnableArgs onGroupItemClicked) { @@ -64,58 +90,60 @@ public class OrdiniUscitaElencoAdapter extends ExtendedSectionedRecyclerView { - if(this.mOnItemChecked != null) this.mOnItemChecked.run(listModel); + if (this.mOnItemChecked != null) this.mOnItemChecked.run(listModel); }); holder.mBinding.getRoot().setOnClickListener(v -> { listModel.getSelectedObservable().set(!listModel.getSelectedObservable().get()); }); } - - @Override - public boolean onPlaceSubheaderBetweenItems(int position) { - - if (getItemSize() == 1) return true; - else if (getItemSize() > 1) { - OrdiniUscitaElencoListModel compare1 = this.mDataset.get(position); - OrdiniUscitaElencoListModel compare2 = this.mDataset.get(position + 1); - - return !UtilityString.equalsIgnoreCase(compare1.getGroupTitle(), compare2.getGroupTitle()); - } - - return true; - } } diff --git a/app/src/main/res/layout/fragment_main_ordini_uscita__list_group_model.xml b/app/src/main/res/layout/fragment_main_ordini_uscita__list_group_model.xml index 38792a6d..4ca47ca2 100644 --- a/app/src/main/res/layout/fragment_main_ordini_uscita__list_group_model.xml +++ b/app/src/main/res/layout/fragment_main_ordini_uscita__list_group_model.xml @@ -1,101 +1,94 @@ - - - - - + - - + android:paddingStart="4dp" + android:paddingEnd="12dp" + android:paddingVertical="4dp" + android:background="@color/full_white"> + + android:layout_width="0dp" + android:layout_height="0dp" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintWidth="8dp"/> - + + app:checked="@{selected}" + app:layout_constraintStart_toEndOf="@id/empty_view" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" /> + + - + + - - - - - - - - - - - - - - - + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_main_ordini_uscita__list_model.xml b/app/src/main/res/layout/fragment_main_ordini_uscita__list_model.xml index bf46c73f..89ca2ac9 100644 --- a/app/src/main/res/layout/fragment_main_ordini_uscita__list_model.xml +++ b/app/src/main/res/layout/fragment_main_ordini_uscita__list_model.xml @@ -1,5 +1,5 @@ - - - +