Android:新闻源应用程序在执行时崩溃

时间:2016-02-03 06:26:44

标签: android news-feed

我开发了一款带有新闻源功能的应用。应用程序在设备中执行时崩溃。我的编码和错误logcat如下。

MainActivity.java:

public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
private ListView listView;
private FeedListAdapter listAdapter;
private List<FeedItem> feedItems;
private String URL_FEED = "http://api.androidhive.info/feed/feed.json";

@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    listView = (ListView) findViewById(R.id.list);

    feedItems = new ArrayList<FeedItem>();

    listAdapter = new FeedListAdapter(this, feedItems);
    listView.setAdapter(listAdapter);

    // These two lines not needed,
    // just to get the look of facebook (changing background color & hiding the icon)
    getActionBar().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#3b5998")));
    getActionBar().setIcon(
            new ColorDrawable(getResources().getColor(android.R.color.transparent)));

    // We first check for cached request
    Cache cache = AppController.getInstance().getRequestQueue().getCache();
    Entry entry = cache.get(URL_FEED);
    if (entry != null) {
        // fetch the data from cache
        try {
            String data = new String(entry.data, "UTF-8");
            try {
                parseJsonFeed(new JSONObject(data));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

    } else {
        // making fresh volley request and getting json
        JsonObjectRequest jsonReq = new JsonObjectRequest(Method.GET,
                URL_FEED, null, new Response.Listener<JSONObject>() {

            @Override
            public void onResponse(JSONObject response) {
                VolleyLog.d(TAG, "Response: " + response.toString());
                if (response != null) {
                    parseJsonFeed(response);
                }
            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                VolleyLog.d(TAG, "Error: " + error.getMessage());
            }
        });

        // Adding request to volley request queue
        AppController.getInstance().addToRequestQueue(jsonReq);
    }

}

/**
 * Parsing json reponse and passing the data to feed view list adapter
 * */
private void parseJsonFeed(JSONObject response) {
    try {
        JSONArray feedArray = response.getJSONArray("feed");

        for (int i = 0; i < feedArray.length(); i++) {
            JSONObject feedObj = (JSONObject) feedArray.get(i);

            FeedItem item = new FeedItem();
            item.setId(feedObj.getInt("id"));
            item.setName(feedObj.getString("name"));

            // Image might be null sometimes
            String image = feedObj.isNull("image") ? null : feedObj
                    .getString("image");
            item.setImge(image);
            item.setStatus(feedObj.getString("status"));
            item.setProfilePic(feedObj.getString("profilePic"));
            item.setTimeStamp(feedObj.getString("timeStamp"));

            // url might be null sometimes
            String feedUrl = feedObj.isNull("url") ? null : feedObj
                    .getString("url");
            item.setUrl(feedUrl);

            feedItems.add(item);
        }

        // notify data changes to list adapater
        listAdapter.notifyDataSetChanged();
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

}

FeedImageView.java:

public class FeedImageView extends ImageView {

public interface ResponseObserver {
    public void onError();

    public void onSuccess();
}

private ResponseObserver mObserver;

public void setResponseObserver(ResponseObserver observer) {
    mObserver = observer;
}

/**
 * The URL of the network image to load
 */
private String mUrl;

/**
 * Resource ID of the image to be used as a placeholder until the network
 * image is loaded.
 */
private int mDefaultImageId;

/**
 * Resource ID of the image to be used if the network response fails.
 */
private int mErrorImageId;

/**
 * Local copy of the ImageLoader.
 */
private ImageLoader mImageLoader;

/**
 * Current ImageContainer. (either in-flight or finished)
 */
private ImageContainer mImageContainer;

public FeedImageView(Context context) {
    this(context, null);
}

public FeedImageView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public FeedImageView(Context context, AttributeSet attrs,
                     int defStyle) {
    super(context, attrs, defStyle);
}


public void setImageUrl(String url, ImageLoader imageLoader) {
    mUrl = url;
    mImageLoader = imageLoader;
    // The URL has potentially changed. See if we need to load it.
    loadImageIfNecessary(false);
}

/**
 * Sets the default image resource ID to be used for this view until the
 * attempt to load it completes.
 */
public void setDefaultImageResId(int defaultImage) {
    mDefaultImageId = defaultImage;
}

/**
 * Sets the error image resource ID to be used for this view in the event
 * that the image requested fails to load.
 */
public void setErrorImageResId(int errorImage) {
    mErrorImageId = errorImage;
}

/**
 * Loads the image for the view if it isn't already loaded.
 *
 * @param isInLayoutPass
 *            True if this was invoked from a layout pass, false otherwise.
 */
private void loadImageIfNecessary(final boolean isInLayoutPass) {
    final int width = getWidth();
    int height = getHeight();

    boolean isFullyWrapContent = getLayoutParams() != null
            && getLayoutParams().height == LayoutParams.WRAP_CONTENT
            && getLayoutParams().width == LayoutParams.WRAP_CONTENT;
    // if the view's bounds aren't known yet, and this is not a
    // wrap-content/wrap-content
    // view, hold off on loading the image.
    if (width == 0 && height == 0 && !isFullyWrapContent) {
        return;
    }

    // if the URL to be loaded in this view is empty, cancel any old
    // requests and clear the
    // currently loaded image.
    if (TextUtils.isEmpty(mUrl)) {
        if (mImageContainer != null) {
            mImageContainer.cancelRequest();
            mImageContainer = null;
        }
        setDefaultImageOrNull();
        return;
    }

    // if there was an old request in this view, check if it needs to be
    // canceled.
    if (mImageContainer != null && mImageContainer.getRequestUrl() != null) {
        if (mImageContainer.getRequestUrl().equals(mUrl)) {
            // if the request is from the same URL, return.
            return;
        } else {
            // if there is a pre-existing request, cancel it if it's
            // fetching a different URL.
            mImageContainer.cancelRequest();
            setDefaultImageOrNull();
        }
    }

    // The pre-existing content of this view didn't match the current URL.
    // Load the new image
    // from the network.
    ImageContainer newContainer = mImageLoader.get(mUrl,
            new ImageListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    if (mErrorImageId != 0) {
                        setImageResource(mErrorImageId);
                    }

                    if (mObserver != null) {
                        mObserver.onError();
                    }
                }

                @Override
                public void onResponse(final ImageContainer response,
                                       boolean isImmediate) {
                    // If this was an immediate response that was delivered
                    // inside of a layout
                    // pass do not set the image immediately as it will
                    // trigger a requestLayout
                    // inside of a layout. Instead, defer setting the image
                    // by posting back to
                    // the main thread.
                    if (isImmediate && isInLayoutPass) {
                        post(new Runnable() {
                            @Override
                            public void run() {
                                onResponse(response, false);
                            }
                        });
                        return;
                    }

                    int bWidth = 0, bHeight = 0;
                    if (response.getBitmap() != null) {

                        setImageBitmap(response.getBitmap());
                        bWidth = response.getBitmap().getWidth();
                        bHeight = response.getBitmap().getHeight();
                        adjustImageAspect(bWidth, bHeight);

                    } else if (mDefaultImageId != 0) {
                        setImageResource(mDefaultImageId);
                    }

                    if (mObserver != null) {
                        mObserver.onSuccess();

                    }
                }
            });

    // update the ImageContainer to be the new bitmap container.
    mImageContainer = newContainer;

}

private void setDefaultImageOrNull() {
    if (mDefaultImageId != 0) {
        setImageResource(mDefaultImageId);
    } else {
        setImageBitmap(null);
    }
}

@Override
protected void onLayout(boolean changed, int left, int top, int right,
                        int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    loadImageIfNecessary(true);
}

@Override
protected void onDetachedFromWindow() {
    if (mImageContainer != null) {
        // If the view was bound to an image request, cancel it and clear
        // out the image from the view.
        mImageContainer.cancelRequest();
        setImageBitmap(null);
        // also clear out the container so we can reload the image if
        // necessary.
        mImageContainer = null;
    }
    super.onDetachedFromWindow();
}

@Override
protected void drawableStateChanged() {
    super.drawableStateChanged();
    invalidate();
}

/*
 * Adjusting imageview height
 * */
private void adjustImageAspect(int bWidth, int bHeight) {
    LinearLayout.LayoutParams params = (LayoutParams) getLayoutParams();

    if (bWidth == 0 || bHeight == 0)
        return;

    int swidth = getWidth();
    int new_height = 0;
    new_height = swidth * bHeight / bWidth;
    params.width = swidth;
    params.height = new_height;
    setLayoutParams(params);
}
}

LruBitmapCache.java:

public class LruBitmapCache extends LruCache<String, Bitmap> implements
    ImageCache {
public static int getDefaultLruCacheSize() {
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
    final int cacheSize = maxMemory / 8;

    return cacheSize;
}

public LruBitmapCache() {
    this(getDefaultLruCacheSize());
}

public LruBitmapCache(int sizeInKiloBytes) {
    super(sizeInKiloBytes);
}

@Override
protected int sizeOf(String key, Bitmap value) {
    return value.getRowBytes() * value.getHeight() / 1024;
}

@Override
public Bitmap getBitmap(String url) {
    return get(url);
}

@Override
public void putBitmap(String url, Bitmap bitmap) {
    put(url, bitmap);
}
}

FeedItem.java:

public class FeedItem {
private int id;
private String name, status, image, profilePic, timeStamp, url;

public FeedItem() {
}

public FeedItem(int id, String name, String image, String status,
                String profilePic, String timeStamp, String url) {
    super();
    this.id = id;
    this.name = name;
    this.image = image;
    this.status = status;
    this.profilePic = profilePic;
    this.timeStamp = timeStamp;
    this.url = url;
}

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getImge() {
    return image;
}

public void setImge(String image) {
    this.image = image;
}

public String getStatus() {
    return status;
}

public void setStatus(String status) {
    this.status = status;
}

public String getProfilePic() {
    return profilePic;
}

public void setProfilePic(String profilePic) {
    this.profilePic = profilePic;
}

public String getTimeStamp() {
    return timeStamp;
}

public void setTimeStamp(String timeStamp) {
    this.timeStamp = timeStamp;
}

public String getUrl() {
    return url;
}

public void setUrl(String url) {
    this.url = url;
}
}

AppController.java:

public class AppController extends Application {

public static final String TAG = AppController.class.getSimpleName();

private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
LruBitmapCache mLruBitmapCache;

private static AppController mInstance;

@Override
public void onCreate() {
    super.onCreate();
    mInstance = this;
}

public static synchronized AppController getInstance() {
    return mInstance;
}

public RequestQueue getRequestQueue() {
    if (mRequestQueue == null) {
        mRequestQueue = Volley.newRequestQueue(getApplicationContext());
    }

    return mRequestQueue;
}

public ImageLoader getImageLoader() {
    getRequestQueue();
    if (mImageLoader == null) {
        getLruBitmapCache();
        mImageLoader = new ImageLoader(this.mRequestQueue, mLruBitmapCache);
    }

    return this.mImageLoader;
}

public LruBitmapCache getLruBitmapCache() {
    if (mLruBitmapCache == null)
        mLruBitmapCache = new LruBitmapCache();
    return this.mLruBitmapCache;
}

public <T> void addToRequestQueue(Request<T> req, String tag) {
    req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
    getRequestQueue().add(req);
}

public <T> void addToRequestQueue(Request<T> req) {
    req.setTag(TAG);
    getRequestQueue().add(req);
}

public void cancelPendingRequests(Object tag) {
    if (mRequestQueue != null) {
        mRequestQueue.cancelAll(tag);
    }
}
}

FeedListAdapter.java:

public class FeedListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<FeedItem> feedItems;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();

public FeedListAdapter(Activity activity, List<FeedItem> feedItems) {
    this.activity = activity;
    this.feedItems = feedItems;
}

@Override
public int getCount() {
    return feedItems.size();
}

@Override
public Object getItem(int location) {
    return feedItems.get(location);
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    if (inflater == null)
        inflater = (LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    if (convertView == null)
        convertView = inflater.inflate(R.layout.feed_item, null);

    if (imageLoader == null)
        imageLoader = AppController.getInstance().getImageLoader();

    TextView name = (TextView) convertView.findViewById(R.id.name);
    TextView timestamp = (TextView) convertView
            .findViewById(R.id.timestamp);
    TextView statusMsg = (TextView) convertView
            .findViewById(R.id.txtStatusMsg);
    TextView url = (TextView) convertView.findViewById(R.id.txtUrl);
    NetworkImageView profilePic = (NetworkImageView) convertView
            .findViewById(R.id.profilePic);
    FeedImageView feedImageView = (FeedImageView) convertView
            .findViewById(R.id.feedImage1);

    FeedItem item = feedItems.get(position);

    name.setText(item.getName());

    // Converting timestamp into x ago format
    CharSequence timeAgo = DateUtils.getRelativeTimeSpanString(
            Long.parseLong(item.getTimeStamp()),
            System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS);
    timestamp.setText(timeAgo);

    // Chcek for empty status message
    if (!TextUtils.isEmpty(item.getStatus())) {
        statusMsg.setText(item.getStatus());
        statusMsg.setVisibility(View.VISIBLE);
    } else {
        // status is empty, remove from view
        statusMsg.setVisibility(View.GONE);
    }

    // Checking for null feed url
    if (item.getUrl() != null) {
        url.setText(Html.fromHtml("<a href=\"" + item.getUrl() + "\">"
                + item.getUrl() + "</a> "));

        // Making url clickable
        url.setMovementMethod(LinkMovementMethod.getInstance());
        url.setVisibility(View.VISIBLE);
    } else {
        // url is null, remove from the view
        url.setVisibility(View.GONE);
    }

    // user profile pic
    profilePic.setImageUrl(item.getProfilePic(), imageLoader);

    // Feed image
    if (item.getImge() != null) {
        feedImageView.setImageUrl(item.getImge(), imageLoader);
        feedImageView.setVisibility(View.VISIBLE);
        feedImageView
                .setResponseObserver(new FeedImageView.ResponseObserver() {
                    @Override
                    public void onError() {
                    }

                    @Override
                    public void onSuccess() {
                    }
                });
    } else {
        feedImageView.setVisibility(View.GONE);
    }

    return convertView;
}

 }

的Manifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.dothis.newsfeed" >

<uses-permission android:name="android.permission.INTERNET" />

<application
    android:name=".app.AppController"
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER"  />
        </intent-filter>
    </activity>

</application>

</manifest>

Buildgradle:

apply plugin: 'com.android.application'

android {
compileSdkVersion 21
buildToolsVersion "21.1.2"

defaultConfig {
    applicationId "com.example.dothis.newsfeed"
    minSdkVersion 17
    targetSdkVersion 21
    versionCode 1
    versionName "1.0"
}
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
}

dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:21.0.3'
compile files('libs/volley.jar')
}

有人可以帮我确定哪里出错了。非常感谢任何指导和帮助。谢谢。

 02-03 14:08:51.808  30225-30225/com.example.dothis.newsfeed I/SELinux﹕ Function: selinux_android_load_priority [0], There is no sepolicy file.
 02-03 14:08:51.808  30225-30225/com.example.dothis.newsfeed I/SELinux﹕ Function: selinux_android_load_priority [1], There is no sepolicy version file.
 02-03 14:08:51.808  30225-30225/com.example.dothis.newsfeed I/SELinux﹕ Function: selinux_android_load_priority , priority version is VE=GOOGLE_POLICY
 02-03 14:08:51.808  30225-30225/com.example.dothis.newsfeed I/SELinux﹕ selinux_android_seapp_context_reload: seapp_contexts file is loaded from /seapp_contexts
 02-03 14:08:51.818  30225-30225/com.example.dothis.newsfeed D/dalvikvm﹕ Late-enabling CheckJNI
 02-03 14:08:52.008  30225-30225/com.example.dothis.newsfeed D/AbsListView﹕ Get MotionRecognitionManager
 02-03 14:08:52.033  30225-30225/com.example.dothis.newsfeed D/AndroidRuntime﹕ Shutting down VM
 02-03 14:08:52.033  30225-30225/com.example.dothis.newsfeed W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x41bdec08)
 02-03 14:08:52.038  30225-30225/com.example.dothis.newsfeed E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.dothis.newsfeed, PID: 30225
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.dothis.newsfeed/com.example.dothis.newsfeed.MainActivity}: java.lang.NullPointerException
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2413)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2471)
        at android.app.ActivityThread.access$900(ActivityThread.java:175)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1308)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:146)
        at android.app.ActivityThread.main(ActivityThread.java:5603)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
        at dalvik.system.NativeStart.main(Native Method)
 Caused by: java.lang.NullPointerException
        at com.example.dothis.newsfeed.MainActivity.onCreate(MainActivity.java:52)
        at android.app.Activity.performCreate(Activity.java:5458)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1093)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2377)
                  at      android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2471)atandroid.app.ActivityThread.access$900(ActivityThread.java:175)at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1308)at android.os.Handler.dispatchMessage(Handler.java:102)at android.os.Looper.loop(Looper.java:146)at android.app.ActivityThread.main(ActivityThread.java:5603)at java.lang.reflect.Method.invokeNative(Native Method)at java.lang.reflect.Method.invoke(Method.java:515)at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)at     com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)at dalvik.system.NativeStart.main(Native Method)

0 个答案:

没有答案
相关问题