我使用Shopify Android API为Shopify网站制作应用程序,目前示例应用程序只是在简单文本ListView中列出每个产品。任何人都可以帮助我尝试获取图像并将它们显示在ListView中的文本旁边。任何帮助都会很棒,对不起有点新鲜。
ProductListActivity.java
public class ProductListActivity extends SampleListActivity {
static final String EXTRA_COLLECTION_ID = "ProductListActivity.EXTRA_COLLECTION_ID";
private String collectionId;
private ProductDetailsTheme theme;
private boolean useProductDetailsActivity;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState, R.layout.product_list_activity);
setTitle(R.string.choose_product);
useProductDetailsActivity = true;
theme = new ProductDetailsTheme(getResources());
Intent intent = getIntent();
if (intent.hasExtra(EXTRA_COLLECTION_ID)) {
collectionId = intent.getStringExtra(EXTRA_COLLECTION_ID);
}
theme.setStyle(ProductDetailsTheme.Style.LIGHT);
theme.setShowProductImageBackground(false);
}
@Override
protected void onResume() {
super.onResume();
// If we haven't already loaded the products from the store, do it now
if (listView.getAdapter() == null && !isFetching) {
isFetching = true;
showLoadingDialog(R.string.loading_data);
Callback<List<Product>> callback = new Callback<List<Product>>() {
@Override
public void success(List<Product> products, Response response) {
isFetching = false;
dismissLoadingDialog();
onFetchedProducts(products);
}
@Override
public void failure(RetrofitError error) {
isFetching = false;
onError(error);
}
};
if (collectionId != null) {
getSampleApplication().getProducts(collectionId, callback);
} else {
getSampleApplication().getAllProducts(callback);
}
}
}
/**
* Once the products are fetched from the server, set our listView adapter so that the products appear on screen.
*
* @param products
*/
private void onFetchedProducts(final List<Product> products) {
runOnUiThread(new Runnable() {
@Override
public void run() {
List<String> productTitles = new ArrayList<String>();
for (Product product : products) {
productTitles.add(product.getTitle());
}
listView.setAdapter(new ArrayAdapter<>(ProductListActivity.this, R.layout.simple_list_item, productTitles));
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (useProductDetailsActivity) {
launchProductDetailsActivity(products.get(position));
} else {
createCheckout(products.get(position));
}
}
});
}
});
}
private void launchProductDetailsActivity(Product product) {
getSampleApplication().launchProductDetailsActivity(this, product, theme);
}
/**
* When the user selects a product, create a new checkout for that product.
*
* @param product
*/
private void createCheckout(final Product product) {
showLoadingDialog(R.string.syncing_data);
getSampleApplication().createCheckout(product, new Callback<Checkout>() {
@Override
public void success(Checkout checkout, Response response) {
dismissLoadingDialog();
onCheckoutCreated(checkout);
}
@Override
public void failure(RetrofitError error) {
onError(error);
}
});
}
/**
* If the selected product requires shipping, show the list of shipping rates so the user can pick one.
* Otherwise, skip to the discounts activity (gift card codes and discount codes).
*
* @param checkout
*/
private void onCheckoutCreated(Checkout checkout) {
if (checkout.isRequiresShipping()) {
startActivity(new Intent(ProductListActivity.this, ShippingRateListActivity.class));
} else {
startActivity(new Intent(ProductListActivity.this, DiscountActivity.class));
}
}
}
SampleListActivity.java
public class SampleListActivity extends SampleActivity {
protected ListView listView;
protected boolean isFetching;
@Override
protected void onCreate(Bundle savedInstanceState) {
onCreate(savedInstanceState, R.layout.list_activity);
}
protected void onCreate(Bundle savedInstanceState, int layoutId) {
super.onCreate(savedInstanceState);
setContentView(layoutId);
listView = (ListView) findViewById(R.id.list_view);
isFetching = false;
}
}
SampleActivity.java
public class SampleActivity extends AppCompatActivity {
private static final String LOG_TAG = SampleActivity.class.getSimpleName();
// The amount of time in milliseconds to delay between network calls when you are polling for Shipping Rates and Checkout Completion
protected static final long POLL_DELAY = 500;
protected Handler pollingHandler;
private ProgressDialog progressDialog;
private boolean webCheckoutInProgress;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pollingHandler = new Handler();
initializeProgressDialog();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
@Override
protected void onResume() {
super.onResume();
// If we are being launched by a url scheme, check the scheme and retrieve the checkout token if provided
Intent intent = getIntent();
Uri uri = intent.getData();
String scheme = getString(R.string.web_return_to_scheme);
if (uri != null && TextUtils.equals(uri.getScheme(), scheme)) {
webCheckoutInProgress = false;
// If the app was launched using the scheme, we know we just successfully completed an order
onCheckoutComplete();
} else {
// If a Web checkout was previously launched, we should check its status
if (webCheckoutInProgress && getSampleApplication().getCheckout() != null) {
pollCheckoutCompletionStatus(getSampleApplication().getCheckout());
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (progressDialog != null) {
progressDialog.dismiss();
}
}
protected SampleApplication getSampleApplication() {
return (SampleApplication) getApplication();
}
/**
* Initializes a simple progress dialog that gets presented while the app is communicating with the server.
*/
private void initializeProgressDialog() {
if (progressDialog != null) {
progressDialog.dismiss();
}
progressDialog = new ProgressDialog(this);
progressDialog.setIndeterminate(true);
progressDialog.setTitle(getString(R.string.please_wait));
progressDialog.setCancelable(true);
progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
SampleActivity.this.finish();
}
});
}
/**
* Present the progress dialog.
*
* @param messageId The identifier (R.string value) of the string to display in the dialog.
*/
protected void showLoadingDialog(final int messageId) {
runOnUiThread(new Runnable() {
@Override
public void run() {
progressDialog.setMessage(getString(messageId));
progressDialog.show();
}
});
}
protected void dismissLoadingDialog() {
runOnUiThread(new Runnable() {
@Override
public void run() {
progressDialog.dismiss();
}
});
}
protected void onError(RetrofitError error) {
onError(BuyClient.getErrorBody(error));
}
/**
* When we encounter an error with one of our network calls, we abort and return to the previous activity.
* In a production app, you'll want to handle these types of errors more gracefully.
*
* @param errorMessage
*/
protected void onError(String errorMessage) {
progressDialog.dismiss();
Log.e(LOG_TAG, "Error: " + errorMessage);
Toast.makeText(this, R.string.error, Toast.LENGTH_LONG).show();
finish();
}
/**
* Use the latest Checkout objects details to populate the text views in the order summary section.
*/
protected void updateOrderSummary() {
final Checkout checkout = getSampleApplication().getCheckout();
if (checkout == null) {
return;
}
((TextView) findViewById(R.id.line_item_price_value)).setText('$' + checkout.getLineItems().get(0).getPrice());
double totalDiscount = 0;
Discount discount = checkout.getDiscount();
if (discount != null && !TextUtils.isEmpty(discount.getAmount())) {
totalDiscount += Double.parseDouble(discount.getAmount());
}
((TextView) findViewById(R.id.discount_value)).setText("-$" + Double.toString(totalDiscount));
double totalGiftCards = 0;
List<GiftCard> giftCards = checkout.getGiftCards();
if (giftCards != null) {
for (GiftCard giftCard : giftCards) {
if (!TextUtils.isEmpty(giftCard.getAmountUsed())) {
totalGiftCards += Double.parseDouble(giftCard.getAmountUsed());
}
}
}
((TextView) findViewById(R.id.gift_card_value)).setText("-$" + Double.toString(totalGiftCards));
((TextView) findViewById(R.id.taxes_value)).setText('$' + checkout.getTotalTax());
((TextView) findViewById(R.id.total_value)).setText('$' + checkout.getPaymentDue());
if (checkout.getShippingRate() != null) {
((TextView) findViewById(R.id.shipping_value)).setText('$' + checkout.getShippingRate().getPrice());
} else {
((TextView) findViewById(R.id.shipping_value)).setText("N/A");
}
}
/**
* Polls until the web checkout has completed.
*
* @param checkout the checkout to check the status on
*/
protected void pollCheckoutCompletionStatus(final Checkout checkout) {
showLoadingDialog(R.string.getting_checkout_status);
getSampleApplication().getCheckoutCompletionStatus(new Callback<Boolean>() {
@Override
public void success(Boolean complete, Response response) {
if (complete) {
dismissLoadingDialog();
onCheckoutComplete();
} else {
pollingHandler.postDelayed(new Runnable() {
@Override
public void run() {
pollCheckoutCompletionStatus(checkout);
}
}, POLL_DELAY);
}
}
@Override
public void failure(RetrofitError error) {
onError(error);
}
});
}
/**
* When our polling determines that the checkout is completely processed, show a toast.
*/
private void onCheckoutComplete() {
dismissLoadingDialog();
webCheckoutInProgress = false;
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(SampleActivity.this, R.string.checkout_complete, Toast.LENGTH_LONG).show();
}
});
}
}
这可能也是有用的Shopify API产品
package com.shopify.buy.model;
import android.text.TextUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.annotations.SerializedName;
import com.shopify.buy.dataprovider.BuyClientFactory;
import com.shopify.buy.utils.DateUtility;
import com.shopify.buy.utils.DateUtility.DateDeserializer;
import java.util.ArrayList;
import java.util.Date;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* A {@code Product} is an individual item for sale in a Shopify store.
*/
public class Product extends ShopifyObject {
@SerializedName("product_id")
private String productId;
@SerializedName("channel_id")
private String channelId;
private String title;
private String handle;
@SerializedName("body_html")
private String bodyHtml;
@SerializedName("published_at")
private Date publishedAtDate;
@SerializedName("created_at")
private Date createdAtDate;
@SerializedName("updated_at")
private Date updatedAtDate;
private String vendor;
@SerializedName("product_type")
private String productType;
private List<ProductVariant> variants;
private List<Image> images;
private List<Option> options;
private String tags;
private Set<String> tagSet;
private boolean available;
private boolean published;
/**
* @return {@code true} if this product has been published on the store, {@code false} otherwise.
*/
public boolean isPublished() {
return published;
}
/**
* @return The unique identifier for this product.
*/
public String getProductId() {
return productId;
}
/**
* @return The unique identifier of the Mobile App sales channel for this store.
*/
public String getChannelId() {
return channelId;
}
/**
* @return The title of this product.
*/
public String getTitle() {
return title;
}
/**
* @return The handle of the product. Can be used to construct links to the web page for the product.
*/
public String getHandle() {
return handle;
}
/**
* @return The description of the product, complete with HTML formatting.
*/
public String getBodyHtml() {
return bodyHtml;
}
/**
* Use {@link #getPublishedAtDate() getPublishedAtDate()}.
*/
@Deprecated
public String getPublishedAt() {
return publishedAtDate == null ? null : DateUtility.createDefaultDateFormat().format(publishedAtDate);
}
/**
* Use {@link #getCreatedAtDate() getCreatedAtDate()}.
*/
@Deprecated
public String getCreatedAt() {
return createdAtDate == null ? null : DateUtility.createDefaultDateFormat().format(createdAtDate);
}
/**
* Use {@link #getUpdatedAtDate() getUpdatedAtDate()}.
*/
@Deprecated
public String getUpdatedAt() {
return updatedAtDate == null ? null : DateUtility.createDefaultDateFormat().format(updatedAtDate);
}
/**
* @return The date this product was published.
*/
public Date getPublishedAtDate() {
return publishedAtDate;
}
/**
* @return The date this product was created.
*/
public Date getCreatedAtDate() {
return createdAtDate;
}
/**
* @return The date this product was last updated.
*/
public Date getUpdatedAtDate() {
return updatedAtDate;
}
/**
* @return The name of the vendor of this product.
*/
public String getVendor() {
return vendor;
}
/**
* @return The categorization that this product was tagged with, commonly used for filtering and searching.
*/
public String getProductType() {
return productType;
}
/**
* @return A list of additional categorizations that a product can be tagged with, commonly used for filtering and searching. Each tag has a character limit of 255.
*/
public Set<String> getTags() { return tagSet; }
/**
* @return A list {@link ProductVariant} objects, each one representing a different version of this product.
*/
public List<ProductVariant> getVariants() {
return variants;
}
/**
* @return A list of {@link Image} objects, each one representing an image associated with this product.
*/
public List<Image> getImages() {
return images;
}
/**
* @return {code true} if this product has at least one image, {@code false} otherwise.
*/
public boolean hasImage() {
return images != null && !images.isEmpty();
}
/**
* @return A list of {@link Option} objects, which can be used to select a specific {@link ProductVariant}.
*/
public List<Option> getOptions() {
return options;
}
/**
* @return {@code true} if this product is in stock and available for purchase, {@code false} otherwise.
*/
public boolean isAvailable() { return available; }
/**
* For internal use only.
*/
public boolean hasDefaultVariant() {
return variants != null && variants.size() == 1 && variants.get(0).getTitle().equals("Default Title");
}
/**
* Returns the {@code Image} for the {@code ProductVariant} with the given id
* @param variant the {@link ProductVariant} to find the {@link Image}
* @return the {@link Image} corresponding to the {@link ProductVariant} if one was found, otherwise the {@code Image} for the {@link Product}. This may return null if no applicable images were found.
*/
public Image getImage(ProductVariant variant) {
if (variant == null) {
throw new NullPointerException("variant cannot be null");
}
List<Image> images = getImages();
if (images == null || images.size() < 1) {
// we did not find any images
return null;
}
for (Image image : images) {
if (image.getVariantIds() != null && image.getVariantIds().contains(variant.getId())) {
return image;
}
}
// The variant did not have an image, use the default image in the Product
return images.get(0);
}
/**
* @param optionValues A list of {@link OptionValue} objects that represent a specific variant selection.
* @return The {@link ProductVariant} that matches the given list of the OptionValues, or {@code null} if no such variant exists.
*/
public ProductVariant getVariant(List<OptionValue> optionValues) {
if (optionValues == null) {
return null;
}
int numOptions = optionValues.size();
for (ProductVariant variant : variants) {
for (int i = 0; i < numOptions; i++) {
if (!variant.getOptionValues().get(i).getValue().equals(optionValues.get(i).getValue())) {
break;
} else if (i == numOptions - 1) {
return variant;
}
}
}
return null;
}
public static class ProductDeserializer implements JsonDeserializer<Product> {
@Override
public Product deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return fromJson(json.toString());
}
}
/**
* A product object created using the values in the JSON string.
*/
public static Product fromJson(String json) {
Gson gson = BuyClientFactory.createDefaultGson(Product.class);
Product product = gson.fromJson(json, Product.class);
List<ProductVariant> variants = product.getVariants();
if (variants != null) {
for (ProductVariant variant : variants) {
variant.productId = Long.parseLong(product.productId);
variant.productTitle = product.getTitle();
}
}
// Create the tagSet.
product.tagSet = new HashSet<>();
// Populate the tagSet from the comma separated list.
if (!TextUtils.isEmpty(product.tags)) {
for (String tag : product.tags.split(",")) {
String myTag = tag.trim();
product.tagSet.add(myTag);
}
}
return product;
}
}
simple_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:padding="@dimen/spacing_16dp"
android:textColor="@android:color/black"
android:textSize="@dimen/text_large">
</TextView>