Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
675 views
in Technique[技术] by (71.8m points)

android - Getting error in existing code after updating support repository to 23.1.0

When I am running my project using support libraries 23.0.0, I am not getting any error, but today when I updated my support repository to 23.1.0, the code of my activity is exactly same in both versions of using support libraries. I am getting the following error:

10-27 14:56:31.734 26271-26271/com.galleri5.android E/AndroidRuntime: FATAL EXCEPTION: main
10-27 14:56:31.734 26271-26271/com.galleri5.android E/AndroidRuntime: Process: com.galleri5.android, PID: 26271
10-27 14:56:31.734 26271-26271/com.galleri5.android E/AndroidRuntime: java.lang.IllegalArgumentException: Target must not be null.
10-27 14:56:31.734 26271-26271/com.galleri5.android E/AndroidRuntime:     at com.squareup.picasso.RequestCreator.into(RequestCreator.java:618)
10-27 14:56:31.734 26271-26271/com.galleri5.android E/AndroidRuntime:     at com.squareup.picasso.RequestCreator.into(RequestCreator.java:601)
10-27 14:56:31.734 26271-26271/com.galleri5.android E/AndroidRuntime:     at com.galleri5.android.activities.HomeActivity$3.success(HomeActivity.java:155)
10-27 14:56:31.734 26271-26271/com.galleri5.android E/AndroidRuntime:     at com.galleri5.android.activities.HomeActivity$3.success(HomeActivity.java:151)
10-27 14:56:31.734 26271-26271/com.galleri5.android E/AndroidRuntime:     at retrofit.CallbackRunnable$1.run(CallbackRunnable.java:45)
10-27 14:56:31.734 26271-26271/com.galleri5.android E/AndroidRuntime:     at android.os.Handler.handleCallback(Handler.java:739)
10-27 14:56:31.734 26271-26271/com.galleri5.android E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:95)
10-27 14:56:31.734 26271-26271/com.galleri5.android E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:135)
10-27 14:56:31.734 26271-26271/com.galleri5.android E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5254)
10-27 14:56:31.734 26271-26271/com.galleri5.android E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method)
10-27 14:56:31.734 26271-26271/com.galleri5.android E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:372)
10-27 14:56:31.734 26271-26271/com.galleri5.android E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)
10-27 14:56:31.734 26271-26271/com.galleri5.android E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)
10-27 14:56:32.605 26271-26342/com.galleri5.android E/GAv4: Successfully bound to service but never got onServiceConnected callback

Here is the code of my Activity:

package com.galleri5.android.activities;

import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.design.widget.NavigationView;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.facebook.AccessToken;
import com.facebook.FacebookSdk;
import com.facebook.login.LoginManager;
import com.galleri5.android.Galleri5Application;
import com.galleri5.android.R;
import com.galleri5.android.adapters.FeedAdapter;
import com.galleri5.android.api.FeedAPI;
import com.galleri5.android.api.UserAPI;
import com.galleri5.android.models.FeedItem;
import com.galleri5.android.models.User;
import com.galleri5.android.utils.CircleTransform;
import com.galleri5.android.utils.SourceType;
import com.galleri5.android.utils.TinyDB;
import com.galleri5.android.utils.Utils;
import com.github.clans.fab.FloatingActionMenu;
import com.google.android.gms.analytics.HitBuilders;
import com.google.android.gms.analytics.Tracker;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.picasso.Picasso;

import java.util.List;

import retrofit.Callback;
import retrofit.RequestInterceptor;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
import retrofit.client.OkClient;
import retrofit.client.Response;
import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper;

public class HomeActivity extends AppCompatActivity {

    ListView listView;
    Toolbar toolbar;
    FeedAdapter adapter;
    private DrawerLayout mDrawer;
    String token;
    TinyDB tinyDB;
    int SELECT_FILE = 1;
    static int radius = Utils.dpToPx(90);
    FloatingActionMenu fab;
    List<FeedItem> list;
    int commentIndex, r;
    static boolean commented;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FacebookSdk.sdkInitialize(getApplicationContext());
        setContentView(R.layout.activity_home);

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

        RequestInterceptor requestInterceptor = new RequestInterceptor() {
            @Override
            public void intercept(RequestFacade request) {
                request.addHeader("Accept", "application/json");
                request.addHeader("Authorization", "Token " + token);
            }
        };

        OkHttpClient okHttpClient = new OkHttpClient();
        RestAdapter restAdapter = new RestAdapter.Builder()
                .setClient(new OkClient(okHttpClient))
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .setEndpoint(API)
                .setRequestInterceptor(requestInterceptor)
                .build();

        FeedAPI feedAPI = restAdapter.create(FeedAPI.class);
        feedAPI.getFeed(new Callback<List<FeedItem>>() {
            @Override
            public void success(List<FeedItem> feedItems, Response response) {
                Log.i("Retrofit Info", "Success");
                Log.i("Data", feedItems.toString());
                list = feedItems;
                adapter = new FeedAdapter(HomeActivity.this, list);
                listView.setAdapter(adapter);
            }

            @Override
            public void failure(RetrofitError error) {
                Log.i("Retrofit Error", "Feed Failed");
            }
        });

        if (android.os.Build.VERSION.SDK_INT >= 21) {
            Window window = getWindow();
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            window.setStatusBarColor(Color.parseColor("#e2b509"));
        }

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        final ActionBar ab = getSupportActionBar();
        assert ab != null;

        ab.setHomeButtonEnabled(true);
        ab.setDisplayHomeAsUpEnabled(true);
        ab.setHomeAsUpIndicator(R.drawable.feed_ic_menu);

        // Find our drawer view
        mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        toolbar.setNavigationIcon(R.drawable.feed_ic_menu);

        final Typeface opensans = Typeface.createFromAsset(getAssets(), "fonts/OpenSans-Regular.ttf");
        final ImageView navProfile = (ImageView) findViewById(R.id.navProfilePic);
        final TextView username = (TextView) findViewById(R.id.username);
        final TextView karma = (TextView) findViewById(R.id.textView89);



> UserAPI userAPI = restAdapter.create(UserAPI.class);
>             userAPI.getFeed("-1", "json", new Callback<User>() {
>                 @Override
>                 public void success(final User user, Response response) {
>                     Log.i("USER", "User API successful");
>                     Picasso.with(HomeActivity.this)
>                             .load(user.getDpUrl())
>                             .resize(radius, radius)
>                             .centerCrop()
>                             .transform(new CircleTransform())
>                             .into(navProfile);
>     
>                     username.setText(user.getFirstName());
>                     username.setTypeface(opensans);
>     
>                     karma.setText(String.format("%s Karma Points", Integer.toString(user.getKarma())));
>                     karma.setTypeface(opensans);
>                 }
>     
>                 @Override
>                 public void failure(RetrofitError error) {
>                     Log.i("USER", "User Profile Failed");
>                 }
>             });


        // Find our drawer view
        NavigationView nvDrawer = (NavigationView) findViewById(R.id.nav_view);
        // Setup drawer view
        setupDrawerContent(nvDrawer);

        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDrawer.openDrawer(Gravity.LEFT);
            }
        });

        fab = (FloatingActionMenu) findViewById(R.id.fab);
        fab.setClosedOnTouchOutside(true);

        findViewById(R.id.fabFacebook).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                SourceType type = new SourceType(true, false, false);
                Intent intent = new Intent(HomeActivity.this, FbImageSelectionActivity.class);
                startActivity(intent);
            }
        });

        findViewById(R.id.fabAlbum).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                SourceType type = new SourceType(false, false, true);
                Intent intent = new Intent(
                        Intent.ACTION_PICK,
                        android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                intent.setType("image/*");
                startActivityForResult(
                        Intent.createChooser(intent, "Select File"),
                        SELECT_FILE);
            }
        });

        findViewById(R.id.imageView129).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(HomeActivity.this, SearchActivity.class);
                startActivity(intent);
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        //getMenuInflater().inflate(R.menu.menu_home, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }


    private void setupDrawerContent(NavigationView navigationView) {
        navigationView.setNavigationItemSelectedListener(
                new NavigationView.OnNavigationItemSelectedListener() {
                    @Override
                    public boolean onNavigationItemSelected(Men

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Update: With the release of Design Support Library 23.1.1, the following method has been added to address this issue:

/**
 * Gets the header view at the specified position.
 *
 * @param index The position at which to get the view from.
 * @return The header view the specified position or null if the position does not exist in this
 * NavigationView.
 */
public View getHeaderView(int index) {
    ...
}

You can also retrieve the number of headers, in case you have more than one:

/**
 * Gets the number of headers in this NavigationView.
 *
 * @return A positive integer representing the number of headers.
 */
public int getHeaderCount() {
    ...
}

In other words, if you use the headerLayout attribute, you can now get access to the view using above method:

View header = navigationView.getHeaderView(0);
ImageView navProfile = (ImageView) header.findViewById(R.id.navProfilePic);

Original answer below left intact for background and/or educational purposes.


I'm going to make an educated guess and say that the following line is probably inflating a view from your NavigationView's header layout:

final ImageView navProfile = (ImageView) findViewById(R.id.navProfilePic);

Where the header layout is given to the NavigationView using:

app:headerLayout="@layout/nav_drawer_header"

If so, continue reading...

With the 23.1.0 release of the design support library, the internal implementation of NavigationView changed to leverage RecyclerView (rather than ListView). With that change, the header has now become another 'item' in the view, meaning it doesn't become available until after the initial layout pass. As such, with your current code, when the findViewById() lookup executes, the RecyclerView hasn't set up the header yet, and hence the result of the lookup ends up being null.

The 'issue' has been reported and the consensus is that getting the header view is going to be exposed with a new method on the NavigationView (most likely just called getHeaderView()). Until this is rolled out, there are two obvious workarounds I'm aware of.

Workaround #1:

Remove app:headerLayout and inflate and add the header view manually. Then use the resulting layout to look up any views in the header.

View header = navigationView.inflateHeaderView(R.layout.nav_drawer_header);
ImageView navProfile = (ImageView) header.findViewById(R.id.navProfilePic);

Workaround #2:

Don't inflate views until after the initial layout pass. This can easily be accomplished by posting a Runnable to the view's parent's internal message queue, so it gets executed after any pending messages.

View parent = (View) mNavigationView.getParent();
parent.post(new Runnable() {
    @Override public void run() {
        ImageView navProfile = (ImageView) mNavigationView.findViewById(R.id.navProfilePic);
    }
});

Personally, I'd go with #1.

Related:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...