Landlord étude récente des derniers composants père Google - Jetpack
pour être honnête, pour voir qui peut lire le document, mais un combat à la force complètement ignorant. Dire aujourd'hui d'introduire l' paging
utilisation de base, le propriétaire a sauté sur une fosse de deux jours. Ce processus point le plus gênant est, la plupart des documents officiels et les données en ligne sont utilisées langue Kotlin, et , malheureusement , je ne sais pas Kotlin, pour écrire un peu Java.
Avant de lire cet article, je défaut , nous savons tout jetpack
ce qu'il est. Donc , ce n'est plus jetpack introduit, attention à la façon dont l'utilisation de la pagination introduction, cet article sera beaucoup de démo affiché le code de votre compréhension et de référence, ce qui va aussi me présenter à pas sur la fosse.
Cette référence:
Avant de lire cet article, il est préférable de lire ce qui précède deux documents officiels. Le premier chapitre est l'introduction paging
de l' utilisation de base, le second est un supplément au premier article décrit comment personnaliser DataSource
.
1. Demo décrit
Avant l'introduction formelle de l'utilisation de la pagination, nous examinons le résultat final est un peu comment.
L'effet est très simple, il y a un RecyclerView
affichage des données, puis nous glisser vers le bas de la diapositive à une certaine position, paging
demandera automatiquement les données, ce qui est l'effet des demandes radiomessagerie. paging
Le but est d'obtenir la charge de la page, avant de réaliser tout leur propre page Google est le père pour nous d'atteindre. Je dois dire que , jetpack
vraiment parfumé!
2. Préparer les composants
Pour utiliser paging
, nous devons nous préparer quelques petites choses (bien sûr, dépendent de ce guide de base de l'opération est certainement nécessaire, je ne présenterai pas le Kazakhstan).
- DataSource: Comme son nom l'indique, les sources de données, l'acquisition de données est réalisée à travers elle.
- PagedList: la source de données par les données finales acquises
PagedList
à transporter. PourPagedList
, nous pouvons être compris, il est une collection d'une page de données. Chaque demande d'une page un nouvelPagedList
objet.- PagedListAdapter: L'adaptateur est
RecyclerView
deAdapter
. Mais nous utilisonspaging
pour atteindre lesRecyclerView
performances de chargement de page ne peut pas être le successeur directRecyclerView
deAdapter
, mais qui ont besoin d'hériterPagedListAdapter
.
3. DataSource sur mesure
Pour être honnête, la coutume DataSource
est pas difficile, mais pourquoi devrais - je singularisé il? D' abord tous les documents officiels, pour obtenir que ItemKeyedDataSource
, et je suis ici pour réaliser est PositionalDataSource
. Bien que la différence ne soit pas grande, mais toujours un peu différent, parce qu'ici je suis monté deux fosses. Je crois que , grâce à ces deux fosses, a rencontré des problèmes similaires à l'avenir, trouveront des idées de solution.
Avant de coller le code, nous allons jeter un oeil à la mise en œuvre des PositionalDataSource
mises en garde.
Tout d' abord, nous devons examiner la nécessité de mettre en œuvre deux méthodes:
nom de la méthode | sens |
---|---|
loadInitial | Chargement des données initiales, donc à comprendre, les données sont chargées première page. L'image de cela, quand nous avons ouvert la page, cette méthode nécessite un rappel pour obtenir des données. |
loadRange | Une fois les données a été initialisé, le temps de glissement si vous avez besoin de charger des données, il appelle cette méthode. |
Maintenant, laissez-le regard de code à atteindre en fin de compte.
public class ConcertDataSource extends PositionalDataSource<Concert> {
private final Retrofit mRetrofit = new Retrofit.Builder()
.baseUrl("http://api.apiopen.top/")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
private final Service mService;
public ConcertDataSource() {
mService = mRetrofit.create(Service.class);
}
@Override
public void loadInitial(@NonNull LoadInitialParams params, @NonNull final LoadInitialCallback<Concert> callback) {
// fetchItem(0, params.pageSize, new Callback() {
// @Override
// public void onResult(Bean value) {
// callback.onResult(value.getResult(), 0, 2000);
// }
// });
callback.onResult(fetchItems(0, 20), 0, 2000);
}
@Override
public void loadRange(@NonNull LoadRangeParams params, @NonNull final LoadRangeCallback<Concert> callback) {
// fetchItem(params.startPosition, params.loadSize, new Callback() {
// @Override
// public void onResult(Bean value) {
// callback.onResult(value.getResult());
// }
// });
callback.onResult(fetchItems(params.startPosition, params.loadSize));
}
private List<Concert> fetchItems(int startPosition, int pageSize) {
List<Concert> list = new ArrayList<>();
for (int i = startPosition; i < startPosition + pageSize; i++) {
Concert concert = new Concert();
concert.setAuthor("author = " + i);
concert.setContent("content = " + i);
concert.setTitle("title = " + i);
list.add(concert);
}
return list;
}
private void fetchItem(final int startPosition, int size, final Callback callback) {
mService.getCall(startPosition, size).subscribe(new Observer<Bean>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Bean value) {
callback.onResult(value);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
private interface Callback {
void onResult(Bean value);
}
}
Ensuite, j'ai combiné le code ci - dessus pour introduire deux pit je sauté sur (en fait, ces deux fosses peuvent être fusionnées dans une fosse, tout comme une cause).
Je voudrais décrire mon problème avant que je rencontrais lorsque vous ouvrez l'écran, j'ai trouvé, RecyclerView
n'a pas montré de données, et par débogage, trouvé loadInitial
la méthode pour être rappelé, mais à la fin Adapter
il est itemCount
nul. C'est ce la cause? Regardons maintenant à la loadInitial
mise en œuvre de la méthode:
@Override
public void loadInitial(@NonNull LoadInitialParams params, @NonNull final LoadInitialCallback<Concert> callback) {
// fetchItem(0, params.pageSize, new Callback() {
// @Override
// public void onResult(Bean value) {
// callback.onResult(value.getResult(), 0, 2000);
// }
// });
callback.onResult(fetchItems(0, 20), 0, 2000);
}
Grâce à LoadInitialCallback
la onResult
méthode de passer un total de trois paramètres, ces trois paramètres Qu'est-ce que cela signifie? Prenons LoadInitialCallback
cette classe maintenant.
public abstract static class LoadInitialCallback<T> {
public abstract void onResult(@NonNull List<T> data, int position, int totalCount);
public abstract void onResult(@NonNull List<T> data, int position);
}
LoadInitialCallback
Il existe deux onResult
méthodes. Et je paraissais ici RecyclerView
n'affiche pas de données, parce que je dois appeler les deux paramètres de onResult
la méthode, ce qui conduit totalCount
à 0, afin de ne pas révéler des données.
Le deuxième problème est que les données sont affichées, mais les données sont toujours la page affichée, cette loadRange
méthode est pas appelée. En fait , totalCount
causé, quand je résolu le premier problème, directement au totalCount
passage est List
le size
(supposé être le N). En d' autres termes, PositionalDataSource
le total final ne sera obtenir les données du N, parce que la taille de la première page est exactement équivalente à N, donc il ne sera pas appeler la loadRange
méthode pour charger plus de données.
3. Créez un ViewModel
Je crois plus familier avec JetPack
les étudiants savons tous que dans Jetpack
l'intérieur de l' architecture est recommandé que chaque page la tenue d' une ViewModel
cible, afin d'assurer l' exactitude des données et éviter d' autres problèmes. Cet article n'est pas présenté ViewModel
, les élèves ne comprennent pas peuvent regarder le document officiel, qui est le lien: ViewModel Une partie de la vue d' ensemble Android Jetpack .
Avant, nous avions une coutume réussie DataSource
, maintenant, regardons comment utiliser ViewModel
maintenant DataSource
connecté.
Tout d' abord, nous devons créer une classe d'usine pour créer DataSource
un objet, dans ce Jetpack
cadre , il est un besoin fondamental.
public class ConcertFactory extends DataSource.Factory<Integer, Concert> {
private MutableLiveData<ConcertDataSource> mSourceLiveData =
new MutableLiveData<>();
@Override
public DataSource<Integer, Concert> create() {
ConcertDataSource concertDataSource = new ConcertDataSource();
mSourceLiveData.postValue(concertDataSource);
return concertDataSource;
}
}
Quant à savoir pourquoi un besoin MutableLiveData
de DataSource
ce paquet, je ne sais pas grand - chose à ce sujet, le document officiel est écrit donc (sans doute DataSource
l'auditeur Activity
ou Fragment
le cycle de vie pour assurer que seul le (état actif dans la page onStart
ou onResume
) pour obtenir des données).
En second lieu , il est de créer le correspondant ViewModel
:
public class ConcertViewModel extends ViewModel {
private final LiveData<PagedList<Concert>> convertList;
private DataSource<Integer, Concert> concertDataSource;
public ConcertViewModel() {
ConcertFactory concertFactory = new ConcertFactory();
concertDataSource = concertFactory.create();
convertList = new LivePagedListBuilder<>(concertFactory, 20).build();
}
public void invalidateDataSource() {
concertDataSource.invalidate();
}
public LiveData<PagedList<Concert>> getConvertList() {
return convertList;
}
}
4. RecyclerView
Tout d' abord, regardons la Adapter
définition:
public class RecyclerAdapter extends PagedListAdapter<Concert, RecyclerAdapter.RecyclerViewHolder> {
protected RecyclerAdapter() {
super(DIFF_CALLBACK);
}
@NonNull
@Override
public RecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recyclerview, parent, false);
return new RecyclerViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull RecyclerViewHolder holder, int position) {
Concert concert = getItem(position);
if (concert != null) {
holder.mTitleTextView.setText(concert.getTitle());
holder.mAuthorTextView.setText(concert.getAuthor());
holder.mContentTextView.setText(concert.getContent());
}
}
public static class RecyclerViewHolder extends RecyclerView.ViewHolder {
TextView mTitleTextView;
TextView mAuthorTextView;
TextView mContentTextView;
public RecyclerViewHolder(View itemView) {
super(itemView);
mTitleTextView = itemView.findViewById(R.id.title);
mAuthorTextView = itemView.findViewById(R.id.author);
mContentTextView = itemView.findViewById(R.id.content);
}
}
private static DiffUtil.ItemCallback<Concert> DIFF_CALLBACK =
new DiffUtil.ItemCallback<Concert>() {
@Override
public boolean areItemsTheSame(Concert oldConcert, Concert newConcert) {
return oldConcert.getTitle().equals(newConcert.getTitle());
}
@Override
public boolean areContentsTheSame(Concert oldConcert,
Concert newConcert) {
return oldConcert.equals(newConcert);
}
};
}
En utilisation PagedListAdapter
, nous notons que, PagedListAdapter
l'implémentation par défaut interne DiffUtil
pour calculer les données de différence, nous passons donc à l' intérieur d' un constructeur DiffUtil.ItemCallback
. Quant à DiffUtil
ce qu'elle est, et son algorithme interne, non présenté ici, les étudiants intéressés peuvent suivre le propriétaire de l' RecyclerView
analyse du code source d'une série d'articles dans un proche avenir, je serai une analyse détaillée de la mise en œuvre interne.
Alors, laissez - nous regarder à l' Activity
intérieur comment utiliser:
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private RecyclerAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = findViewById(R.id.recyclerView);
adapter = new RecyclerAdapter();
ConcertViewModel viewModel =
ViewModelProviders.of(this).get(ConcertViewModel.class);
viewModel.getConvertList().observe(this, concerts -> adapter.submitList(concerts));
mRecyclerView.setAdapter(adapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
mRecyclerView.addItemDecoration(new SimpleDividerDecoration(this));
}
}
De cette façon , la structure entière, n'est pas très simple? Cependant, il peut y avoir des gens ici douteraient, je mettre en œuvre une RecyclerView
charge plus de données, vous me permettent de définir tant la classe, est - ce pas exagéré?
En fait, Jetpack
est le fonctionnaire a recommandé un programme d'architecture App Google, dans cette structure, évitera de nombreux problèmes, tels que les fuites de mémoire et exception de pointeur NULL, et ainsi de suite. La raison d'utiliser cette approche à l' architecture App, nous sommes plein soutien de rien à faire , mais pour résoudre le problème ne peut être résolu dans le cadre du programme-cadre traditionnel. Bien sûr, il peut y avoir d' autres solutions tierces, mais certainement mieux que l' Jetpack
autorité, après tout, le père Google personnellement conçu.
5. Source
Pour vous donner une meilleure compréhension paging
de l'utilisation, je vais télécharger mon code à github, pour votre référence, lien: PagingDemo .
6. Enfin
Je joins mon programme d'apprentissage de la technologie de base Android, l' accès à un contenu pertinent à jouer avec mon GitHub: https://github.com/Meng997998/AndroidJX
Eh bien pas une saison récente interview, vous donner un bien-être: 2017-2019 [octets interview battant Zhenti modèle écrit analytique et curriculum vitae PDF]
Pour des questions face octet battant finition, classé, étape par étape, de base à en profondeur, de facile à Jane.
Le contenu de la discussion en cinq chapitres, des questions de visage informatique de base, les questions de surface des structures de données et algorithmes, questions d'entrevue Java, des questions d'entrevue Android, questions d'entrevue d'autres extensions, un total de section cinq questions non techniques 354.
Accès: préoccupation que je vois introduction personnelle, ou directement clic - moi libre de recevoir
Chaque question est accompagnée d'une réponse standard de référence est d'essai et la digestion d'erreur (vraiment passé beaucoup de temps), il est bon d'écrire des articles comme la réponse.
Gagnez du temps nous allons tous à la recherche, le temps passé sur les bonnes choses. .
achevaient également un ensemble complet de rédaction de curriculum vitae, recrue de printemps confus, entretien des ressources humaines et d'autres questions à résoudre les suggestions de référence sont des avantages aux autres.