我已经尝试了两种方法:同步方法和同步块上的同步块作为LOCK不能同时运行它们,但它似乎对我不起作用。
public class PagingBoundaryCallback extends PagedList.BoundaryCallback<Crypto> {
private static final String LOG_TAG = PagingBoundaryCallback.class.getSimpleName();
private static final String TAG_COIN_MARKET_CAP_API = LOG_TAG + CoinMarketCapApi.class.getSimpleName();
private static final String TAG_CRYPTO_COMPARE_API = LOG_TAG + CryptoCompareApi.class.getSimpleName();
private static final int RESULTS_SIZE = 50;
private static final String TO_SYMBOL = "USD";
private static final int FAVOURITE_FALSE = 0;
private static final Object LOCK = new Object();
private CoinMarketCap coinMarketCapApi;
private CryptoCompare cryptoCompareApi;
private CryptoLocalCache cache;
private int resultsFromRank = 1;
private boolean requestingInProgress = false;
private List<CryptoSimple> cryptoSimpleList;
private List<CryptoDetailed> cryptoDetailedList;
private List<Crypto> cryptoList = new ArrayList<>();
public PagingBoundaryCallback(
CoinMarketCap coinMarketCapApi,
CryptoCompare cryptoCompareApi,
CryptoLocalCache cache) {
this.coinMarketCapApi = coinMarketCapApi;
this.cryptoCompareApi = cryptoCompareApi;
this.cache = cache;
}
@Override
public void onZeroItemsLoaded() {
super.onZeroItemsLoaded();
requestAndSaveData();
}
@Override
public void onItemAtEndLoaded(Crypto itemAtEnd) {
super.onItemAtEndLoaded(itemAtEnd);
requestAndSaveData();
}
private void requestAndSaveData() {
if (requestingInProgress) return;
requestingInProgress = true;
requestCryptoSimple();
requestCryptoDetailed();
createCryptoFromResponses(cryptoSimpleList, cryptoDetailedList);
requestingInProgress = false;
}
private void requestCryptoSimple() {
synchronized (LOCK) {
coinMarketCapApi.requestCoins(resultsFromRank, RESULTS_SIZE).enqueue(
new Callback<CryptoSimpleResponse>() {
@Override
public void onFailure(Call<CryptoSimpleResponse> call, Throwable t) {
Log.d(TAG_COIN_MARKET_CAP_API, "failed to get data");
Log.d(TAG_COIN_MARKET_CAP_API, "Unknown error " + t.getMessage());
}
@Override
public void onResponse(Call<CryptoSimpleResponse> call, Response<CryptoSimpleResponse> response) {
Log.d(TAG_COIN_MARKET_CAP_API, "got response: " + response.toString());
if (response.isSuccessful()) {
cryptoSimpleList = new ArrayList<>();
HashMap<String, CryptoSimple> hashMap = response.body().getItems();
for (Map.Entry<String, CryptoSimple> entry : hashMap.entrySet()) {
CryptoSimple cryptoSimple = entry.getValue();
cryptoSimpleList.add(cryptoSimple);
Log.v("CryptoSimple HashMap", cryptoSimple.toString());
}
Log.v("cryptoSimpleListSize", String.valueOf(cryptoSimpleList.size()));
resultsFromRank += RESULTS_SIZE;
} else {
Log.d(TAG_COIN_MARKET_CAP_API, "Unknown error " + response.errorBody().toString());
}
}
}
);
}
}
private void requestCryptoDetailed() {
synchronized (LOCK) {
StringBuilder cryptoSymbol = new StringBuilder(RESULTS_SIZE);
Log.v("cryptoSimpleListSize", String.valueOf(cryptoSimpleList.size()));
for (CryptoSimple item : cryptoSimpleList) {
cryptoSymbol
.append(item.getSymbol())
.append(",");
}
int cryptoSymbolLength = cryptoSymbol.length();
Log.v("cryptoSymbolLength", String.valueOf(cryptoSymbolLength));
String fromSymbol = cryptoSymbol.delete(cryptoSymbolLength - 1, cryptoSymbolLength).toString();
cryptoCompareApi.requestCoins(fromSymbol, TO_SYMBOL).enqueue(new Callback<CryptoDetailedResponse>() {
@Override
public void onResponse(Call<CryptoDetailedResponse> call, Response<CryptoDetailedResponse> response) {
Log.d(TAG_CRYPTO_COMPARE_API, "got response: " + response.toString());
if (response.isSuccessful()) {
cryptoDetailedList = response.body().getList();
} else {
Log.d(TAG_COIN_MARKET_CAP_API, "Unknown error " + response.errorBody().toString());
}
}
@Override
public void onFailure(Call<CryptoDetailedResponse> call, Throwable t) {
Log.d(TAG_CRYPTO_COMPARE_API, "failed to get data");
Log.d(TAG_CRYPTO_COMPARE_API, "Unknown error " + t.getMessage());
}
});
}
}
private void createCryptoFromResponses(List<CryptoSimple> cryptoSimpleList, List<CryptoDetailed> cryptoDetailedList) {
if (cryptoList.size() != 0)
cryptoList.clear();
for (int i = 0; i < cryptoSimpleList.size(); i++) {
Crypto cryptoItem = new Crypto(
cryptoSimpleList.get(i).getId(),
cryptoSimpleList.get(i).getName(),
cryptoSimpleList.get(i).getSymbol(),
cryptoSimpleList.get(i).getRank(),
cryptoDetailedList.get(i).getPrice(),
cryptoDetailedList.get(i).getTime(),
cryptoDetailedList.get(i).getVolume(),
cryptoDetailedList.get(i).getChangePercentage(),
cryptoDetailedList.get(i).getMarketCap(),
FAVOURITE_FALSE
);
cryptoList.add(cryptoItem);
}
if (cryptoList.size() > 0)
cache.insertCoins(cryptoList);
Log.v(LOG_TAG, "Inserted " + String.valueOf(cryptoList.size()) + " to database");
}}
来自requestCryptoDetailed()的cryptoSimpleList;在将项目添加到requestCryptoSimple()中的cryptoSimpleList之前访问;这就是我得到NullPointerException的原因。就像我说的那样,我已经尝试了两种方法:同一个对象上的同步方法和同步块,但它似乎对我不起作用。
如何运行整个requestCryptoSimple(); requestCryptoDetailed()之前的方法;方法