我发现解决此问题的一种方法是使用 nativescript-image-cache 但这并不总是很好,因为图像加载速度仍然很慢。我想出的解决方案是向 API 添加分页并使用 angular *ngFor 而不是 ListView。这样它们就不会因为 ListView 而消失,并且用户可以加载任意数量的图像,当他们想要它们时,它不会降低性能并且在 UI 方面看起来更好。
如果其他人遇到这样的问题并且不知道该怎么办,这里是代码:
之前(使用 ListView - 不好)
<ListView [items]="feeds" height="100%">
<ng-template let-item="item" class="feed">
<StackLayout>
<StackLayout>
<GridLayout class="feed-user" columns="50,20,*" (tap)="getUserById(item.userId)">
<Image class="user" [src]="item.mainImage" col="0"></Image>
<Label [text]="item.username" class="username" col="2"></Label>
</GridLayout>
<Image *ngIf="item.isImage" class="feed-image" [src]="item.photoUrl"></Image>
<VideoPlayer *ngIf="!item.isImage" [src]="item.photoUrl" autoplay="true" muted="true"
height="300">
</VideoPlayer>
<GridLayout class="like-sect" columns="*,*" (tap)="like(item)">
<Image class="like" col="0" src="~/app/_assets/ui-images/like.png"></Image>
<Label col="1" class="likes" [text]="item.likes"></Label>
</GridLayout>
<Label class="caption" [text]="item.description"></Label>
</StackLayout>
</StackLayout>
</ng-template>
</ListView>
之后(没有 ListView - 好)
<ScrollView [height]="height">
<StackLayout>
<StackLayout *ngFor="let item of feeds">
<StackLayout class="feed-body">
<StackLayout>
<Image *ngIf="item.isImage" class="feed-image" [src]="item.photoUrl"></Image>
<VideoPlayer *ngIf="!item.isImage" [src]="item.photoUrl" autoplay="true" muted="true"
height="300">
</VideoPlayer>
<GridLayout class="like-sect" columns="*,*" (tap)="like(item)">
<Image class="like" col="0" src="~/app/_assets/ui-images/like.png"></Image>
<Label col="1" class="likes" [text]="item.likes"></Label>
</GridLayout>
<StackLayout class="feed-info">
<Label class="caption" [text]="item.description" textWrap="true"></Label>
<Label [text]="item.username + ' | ' + item.dateCreated" (tap)="getUserById(item.userId)"></Label>
</StackLayout>
</StackLayout>
</StackLayout>
<StackLayout class="hr" height="1"></StackLayout>
</StackLayout>
<!-- Instead of this stackLayout below, you should use RadListView and when the user scrolls to the bottom of the screen, it should automatically run the 'nextPage()' function -->
<StackLayout>
<Label *ngIf="!noMoreItems" class="load-more" horizontalAlignment="center" text="Load More.."
(tap)="nextPage()"></Label>
<Label *ngIf="noMoreItems" class="load-more" horizontalAlignment="center"
text="You've viewed everything!"></Label>
</StackLayout>
</StackLayout>
</ScrollView>
这是打字稿文件,如果有人想看的话:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { FeedService } from '~/app/_mocks/feed.service';
import { EventService } from '~/app/_services/event.service';
import * as utils from "tns-core-modules/utils/utils";
import * as application from "tns-core-modules/application"
import { registerElement } from "nativescript-angular/element-registry";
import { Video } from 'nativescript-videoplayer';
import { RouterExtensions } from 'nativescript-angular/router';
import { HttpClient } from '@angular/common/http';
import { GoToService } from '~/app/_services/go-to/go-to.service';
import { UserService } from '~/app/_services/user.service';
registerElement("VideoPlayer", () => Video);
import { screen } from "tns-core-modules/platform/platform"
import { environment } from '~/app/environments/environment';
@Component({
selector: 'ns-feed',
templateUrl: './feed.component.html',
styleUrls: ['./feed.component.css']
})
export class FeedComponent implements OnInit {
constructor(private mockFeedService: FeedService, private eventService: EventService
, private router: RouterExtensions, private http: HttpClient, private goTo: GoToService,
private userService: UserService) { }
baseUrl = environment.apiUrl + 'feeds/'
public isAndroid: boolean;
public isIos: boolean;
feeds: any;
loaded = true
today: '18/12/2019'
show: any;
start = 0
end = 7
pageNumber = 1;
userImg = '~/app/_assets/-user.png'
height: number = screen.mainScreen.heightDIPs * 1;
noMoreItems = false;
ngOnInit() {
if (application.ios) {
this.isAndroid = false;
this.isIos = true;
} else if (application.android) {
this.isAndroid = true;
this.isIos = false;
}
this.getFeed();
this.show = 'false'
console.log(this.feeds)
}
getFeed() {
this.baseUrl = environment.apiUrl + 'feeds' + '?pageNumber=' + this.pageNumber
this.http.get(this.baseUrl).subscribe(response => {
const feeds = response;
this.pushToUi(feeds)
// console.log(this.feeds)
if (!feeds) {
console.log('no response')
}
}, error => {
console.log(error);
});
}
pushToUi(items) {
if (items.length == 0) {
console.log('no items')
this.noMoreItems = true;
}
if (this.feeds) {
this.feeds = this.feeds.concat(items)
} else {
this.feeds = items
}
// this.ArrayOptimization()
}
ArrayOptimization() {
// if (this.feeds.length >= 5) {
// console.log('length > 5, length = ' + this.feeds.length)
// }
// THE CODE BELOW IS THE ACTUAL CODE THAT WILL BE USED:
// THIS MAY NOT EVEN BE NECCESSARY, NEED TO DO TESTING
// if (this.feeds.length >= 11) {
// this.feeds.splice(0, 5)
// console.log(this.feeds.length)
// }
}
getUserById(item) {
let newUrl = 'http://10.0.2.2:5000/api/users/' + item
console.log(newUrl)
this.http.get(newUrl).subscribe(response => {
this.userService.singleUser = response;
console.log(this.userService.singleUser)
this.router.navigate(['/single-user/' + item])
}, error => {
console.log(error);
});
}
like(item) {
console.log(item.likes)
item.likes = item.likes + 1
console.log(item.likes)
}
goToUrl(url) {
utils.openUrl('https://' + url);
}
loadVideoIOS() {
this.router.navigate(['/video'])
}
nextPage() {
this.pageNumber = this.pageNumber + 1
this.getFeed()
}
}