That fuck shit the fascists are using
at master 191 lines 5.8 kB view raw
1package org.signal.pagingtest; 2 3import androidx.annotation.NonNull; 4import androidx.annotation.Nullable; 5import androidx.appcompat.app.AppCompatActivity; 6import androidx.lifecycle.ViewModelProvider; 7import androidx.recyclerview.widget.DiffUtil; 8import androidx.recyclerview.widget.LinearLayoutManager; 9import androidx.recyclerview.widget.RecyclerView; 10 11import android.os.Bundle; 12import android.view.LayoutInflater; 13import android.view.View; 14import android.view.ViewGroup; 15import android.widget.TextView; 16 17import org.signal.paging.PagingController; 18 19import java.util.ArrayList; 20import java.util.List; 21import java.util.Objects; 22import java.util.Optional; 23 24public class MainActivity extends AppCompatActivity implements EventListener { 25 26 private MainViewModel viewModel; 27 28 @Override 29 protected void onCreate(Bundle savedInstanceState) { 30 super.onCreate(savedInstanceState); 31 setContentView(R.layout.activity_main); 32 33 MyAdapter adapter = new MyAdapter(this); 34 RecyclerView list = findViewById(R.id.list); 35 LinearLayoutManager layoutManager = new LinearLayoutManager(this); 36 37 list.setAdapter(adapter); 38 list.setLayoutManager(layoutManager); 39 40 viewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(MainViewModel.class); 41 adapter.setPagingController(viewModel.getPagingController()); 42 viewModel.getList().observe(this, newList -> { 43 adapter.submitList(newList); 44 }); 45 46 findViewById(R.id.invalidate_btn).setOnClickListener(v -> { 47 viewModel.getPagingController().onDataInvalidated(); 48 }); 49 50 findViewById(R.id.down250_btn).setOnClickListener(v -> { 51 int target = Math.min(adapter.getItemCount() - 1, layoutManager.findFirstVisibleItemPosition() + 250); 52 layoutManager.scrollToPosition(target); 53 }); 54 55 findViewById(R.id.up250_btn).setOnClickListener(v -> { 56 int target = Math.max(0, layoutManager.findFirstVisibleItemPosition() - 250); 57 layoutManager.scrollToPosition(target); 58 }); 59 60 findViewById(R.id.prepend_btn).setOnClickListener(v -> { 61 viewModel.prependItems(); 62 }); 63 } 64 65 @Override 66 public void onItemClicked(String key) { 67 viewModel.onItemClicked(key); 68 } 69 70 static class MyAdapter extends RecyclerView.Adapter<MyViewHolder> { 71 72 private final static int TYPE_NORMAL = 1; 73 private final static int TYPE_PLACEHOLDER = -1; 74 75 private final EventListener listener; 76 private final List<Item> data; 77 78 private PagingController<String> controller; 79 80 public MyAdapter(@NonNull EventListener listener) { 81 this.listener = listener; 82 this.data = new ArrayList<>(); 83 84 setHasStableIds(true); 85 } 86 87 @Override 88 public int getItemViewType(int position) { 89 return getItem(position) == null ? TYPE_PLACEHOLDER : TYPE_NORMAL; 90 } 91 92 @Override 93 public int getItemCount() { 94 return data.size(); 95 } 96 97 @Override 98 public long getItemId(int position) { 99 Item item = getItem(position); 100 if (item != null) { 101 return item.key.hashCode(); 102 } else { 103 return 0; 104 } 105 } 106 107 @Override 108 public @NonNull MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 109 switch (viewType) { 110 case TYPE_NORMAL: 111 case TYPE_PLACEHOLDER: 112 return new MyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false)); 113 default: 114 throw new AssertionError(); 115 } 116 } 117 118 @Override 119 public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { 120 holder.bind(getItem(position), position, listener); 121 } 122 123 private Item getItem(int index) { 124 if (controller != null) { 125 controller.onDataNeededAroundIndex(index); 126 } 127 return data.get(index); 128 } 129 130 void setPagingController(PagingController<String> pagingController) { 131 this.controller = pagingController; 132 } 133 134 void submitList(List<Item> list) { 135 DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() { 136 @Override 137 public int getOldListSize() { 138 return data.size(); 139 } 140 141 @Override 142 public int getNewListSize() { 143 return list.size(); 144 } 145 146 @Override 147 public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { 148 String oldKey = Optional.ofNullable(data.get(oldItemPosition)).map(item -> item.key).orElse(null); 149 String newKey = Optional.ofNullable(list.get(newItemPosition)).map(item -> item.key).orElse(null); 150 151 return Objects.equals(oldKey, newKey); 152 } 153 154 @Override 155 public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { 156 Long oldKey = Optional.ofNullable(data.get(oldItemPosition)).map(item -> item.timestamp).orElse(null); 157 Long newKey = Optional.ofNullable(list.get(newItemPosition)).map(item -> item.timestamp).orElse(null); 158 159 return Objects.equals(oldKey, newKey); 160 } 161 }, false); 162 163 result.dispatchUpdatesTo(this); 164 165 data.clear(); 166 data.addAll(list); 167 } 168 } 169 170 static class MyViewHolder extends RecyclerView.ViewHolder { 171 172 TextView textView; 173 174 public MyViewHolder(@NonNull View itemView) { 175 super(itemView); 176 textView = itemView.findViewById(R.id.text); 177 } 178 179 void bind(@Nullable Item item, int position, @NonNull EventListener listener) { 180 if (item != null) { 181 textView.setText(position + " | " + item.key.substring(0, 13) + " | " + System.currentTimeMillis()); 182 textView.setOnClickListener(v -> { 183 listener.onItemClicked(item.key); 184 }); 185 } else { 186 textView.setText(position + " | PLACEHOLDER"); 187 textView.setOnClickListener(null); 188 } 189 } 190 } 191}