【问题标题】:Results from AsyncTask not getting posted to a TextView of ActivityAsyncTask 的结果未发布到 Activity 的 TextView
【发布时间】:2019-01-15 03:55:39
【问题描述】:

所以我试图从我制作的 REST API 中检索所有帖子,以输出到我的 Posts 活动中的文本视图。我可以成功检索 JSON 对象并将它们存储在相应的 ArrayList 中。但是,每当我从 AsyncTask 的onPostExecute 中的Posts 活动中调用我的ListPosts 函数时,它就会说我的postsSect 文本视图为空。

我在想,由于某种原因,R.id 没有被联系到,即使我在我的PostsonCreate 中声明了它。因此,我在 logcat 中收到此错误消息:

01-14 21:43:57.022 16588-16588/com.example.android.androidcraftsappprototype E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.android.androidcraftsappprototype, PID: 16588
    java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Window$Callback android.view.Window.getCallback()' on a null object reference
        at android.support.v7.app.AppCompatDelegateImpl.<init>(AppCompatDelegateImpl.java:249)
        at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:182)
        at android.support.v7.app.AppCompatActivity.getDelegate(AppCompatActivity.java:520)
        at android.support.v7.app.AppCompatActivity.findViewById(AppCompatActivity.java:191)
        at com.example.android.androidcraftsappprototype.WSAdapter$SendPostsRequest.onPostExecute(WSAdapter.java:186)
        at com.example.android.androidcraftsappprototype.WSAdapter$SendPostsRequest.onPostExecute(WSAdapter.java:104)
        at android.os.AsyncTask.finish(AsyncTask.java:695)
        at android.os.AsyncTask.-wrap1(Unknown Source:0)
        at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:712)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6494)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

Posts.java

public class Posts extends AppCompatActivity {

    TextView postsSect;
    Button postsDoneBtn;
    WSAdapter.SendPostsRequest PostsHelper;
    StringBuilder postsBuffer = new StringBuilder();

    @Override
    protected void onResume(){
        super.onResume();
        PostsDetails postDetailsHelper = new PostsDetails();
        //postDetailsHelper.ListPosts();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_posts);

        postsDoneBtn = (Button) findViewById(R.id.PostsDoneButton);
        postsSect = (TextView) findViewById(R.id.PostsSection);

        PostsDetails postDetailsHelper = new PostsDetails();

        postDetailsHelper.callPostDetails("http://192.168.0.18:8000/api/");
        //postDetailsHelper.ListPosts();

        postsDoneBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(Posts.this, MainActivity.class));

            }
        });
    }

    public class PostsDetails {
        //String post_title, post_content;
        ArrayList<Integer> post_id = new ArrayList<Integer>();
        ArrayList<String> post_title = new ArrayList<String>();
        ArrayList<String> post_content = new ArrayList<String>();

        boolean isPDCalled;



        // sets if Post details are called

        // checks if postsDetails functions are called for AsyncTask
        boolean getIsPDCalled(){
            return isPDCalled;
        }

        // calls the execute for AsyncTask
        private void callPostDetails(String theurl){
            PostsHelper = new WSAdapter().new SendPostsRequest();
            // executes AsyncTask
            PostsHelper.execute(theurl);
        }

        // sets values for the posts arrays
        public void setPost(int p_id, String p_title, String p_content) {
            this.post_id.add(p_id);
            this.post_title.add(p_title);
            this.post_content.add(p_content);
        }

        public ArrayList<Integer> getPostID() {
            return this.post_id;
        }

        public ArrayList<String> getPostTitle() {
            return this.post_title;
        }

        public ArrayList<String> getPostContent() {
            return this.post_content;
        }

        // Lists the posts from the database
        public void ListPosts() {
            /////////// add functionality if a post was deleted and was clicked

            int lastFrJSONArray = getPostID().size() - 1;

            postsSect = (TextView) findViewById(R.id.PostsSection);

            // outputs the id of the very first post, something to put to the textview
            postsSect.setText("id: " + getPostID().get(0) + "\n");
            for (int i = lastFrJSONArray; i >= 0; i--)
            {
                // appending the titles and contents of the current post
                postsSect.append("title: " + getPostTitle().get(i) + "\n");
                postsSect.append("content: " + getPostContent().get(i) + "\n");

                // if this is the last post, then don't need to append id for the next post.
                if (i != 0) {
                    postsSect.append("id: " + getPostID().get(i) + "\n");
                }
            }
        }
    }
}

WSAdapter.java

public class WSAdapter {

    /*@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }*/

    public class SendPostsRequest extends AsyncTask<String, String, String> {
        TextView postsSect;
        // Add a pre-execute thing
        HttpURLConnection urlConnection;
        private WeakReference<Activity> mPostReference;

        /*public SendPostsRequest(Activity activity){
            mPostReference = new WeakReference<Activity>(activity);
        }*/

        @Override
        protected String doInBackground(String... params) {

            StringBuilder result = new StringBuilder();

            try {
                urlConnection = (HttpURLConnection) new URL(params[0]).openConnection();
                urlConnection.setRequestMethod("GET");
                urlConnection.connect();

                InputStream in = new BufferedInputStream(urlConnection.getInputStream());

                BufferedReader reader = new BufferedReader(new InputStreamReader(in));

                String line;
                while ((line = reader.readLine()) != null) {
                    result.append(line);
                }

            }catch( Exception e) {
                e.printStackTrace();
            }
            /*finally {
                urlConnection.disconnect();
            }*/

            return result.toString();
        }

        @Override
        protected void onPostExecute(String result) {

            // expecting a response code fro my server upon receiving the POST data
            Log.e("TAG", result);

            Posts.PostsDetails postsHelper = new Posts().new PostsDetails();

            // For posts
            try {
                JSONArray pJObjArray = new JSONArray(result);

                // algorithm for parsing the JSONArray from the Django REST API
                for (int i = 0; i < pJObjArray.length(); i++) {
                    // puts the current iterated JSON object from the array to another temporary object
                    JSONObject pJObj_data = pJObjArray.getJSONObject(i);
                    // inputs necesarry elements to the ListPosts function
                    postsHelper.setPost(pJObj_data.getInt("id"), pJObj_data.getString("post_title"), pJObj_data.getString("post_content"));
                }

            } catch (JSONException e) {
                //Toast.makeText(JSonActivity.this, e.toString(), Toast.LENGTH_LONG).show();
                Log.d("Json","Exception = "+e.toString());
            }

            postsHelper.ListPosts();

        }

    }
}

【问题讨论】:

  • "请忽略我将 AsyncTask 放置到不同活动的事实。" – 这就是造成当前问题的原因。 WSAdapter 实际上并没有被用作Activity,它不应该扩展任何Activity 类。你自己实例化了那个类,它调用findViewById(),它抛出了异常,因为它不是Activity,因为它没有被系统实例化和初始化。我不知道你为什么把SendPostsRequest 设置为一个内部类,但它似乎不需要。为什么不把它作为顶级类呢?
  • 正如@MikeM 所述。在上面的评论中请正确重组您的代码。正如您在代码 WSAdapter extends AppCompatActivity 中提到的那样,没有任何视图与之关联,因此 postsSect = (TextView) findViewById(R.id.PostsSection); 将导致 null only
  • 没有setContentView,你怎么能使用findViewById
  • 哦,好的。我曾尝试在此之前传递活动上下文方法,但将其删除,因为如果活动在asyncTask 完成之前关闭,可能会导致内存泄漏。但我现在会处理你的答案!太感谢了!我没有意识到 AsyncTasks 处于活动中可能是致命的。
  • 好的,所以 WSAdapter 现在不是一个活动,但我仍然遇到同样的错误。我的 AsyncTask 被调用和处理。

标签: java android android-asynctask textview


【解决方案1】:

首先重构你的代码。对于设置文本,使您想要使用的那些字段静态,然后在 AsyncTask 的 onPostExecute 中设置它们的值,否则您可以将 jsonstring 原样返回给您的活动,然后在那里解析它并设置值以获得更好的可读性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多