java - 无法将 [text/plain,UTF-8] 表示形式转换为类 java.lang.String 的对象

标签 java android restlet

我在开发 reSTLet web 服务 + Android 应用程序时遇到了一个奇怪的问题。

当我尝试使用简单的获取从 Web 服务(本地部署在 Tomcat 7.0 上)恢复字符串时,如果来自服务器的字符串太大,Android 应用程序会崩溃并出现 NullPointerException

基本上,方案如下

安卓应用

String retrievedString = clientResource.get();

网络服务器

return serializedString;

serializedString 有(不太)大量的字符(超过 2k 或类似的东西)时,retrievedString 得到一个 null 值.

我不知道这里的问题是什么,但我认为最有可能的原因是内存限制,由于 Android 堆、Java 堆、系统 RAM 甚至可能是 VirtualBox/Genymotion 限制。

您如何看待这个问题,我该如何解决?


编辑

根据要求,这里有更多的代码;我尽量避免不必要的东西和 try/catch block 。

服务器

 ObjectMapper objectMapper = new ObjectMapper();
    FilterProvider excludeThreadFilter =
        new SimpleFilterProvider().addFilter("filter properties by name",
            SimpleBeanPropertyFilter.serializeAllExcept("email", "password",
                "threads", "messages", "subforumsSet", /*"parentSubforum",
                "registeredDate", "threadSubforum"*/));
    String st = objectMapper.writer(excludeThreadFilter).writeValueAsString(lt);
    return st;

客户端

ClientResource cr = new ClientResource("...an ip address...");
    ThreadsInSubforumIdByPage tis = cr.wrap(ThreadsInSubforumIdByPage.class);

      // The line below is null
      String retrievedString = tis.getThreads();
      // The line below raise the NullPointerException
      List<Thread> retrievedList =
        DataHolder.getHolder().getObjectMapper().readValue(
          retrievedString, new TypeReference<List<Thread>>(){});

异常

编辑:好的,我被 logcat 颜色误导了。我使用 Android Studio 才几天,我根本没有注意到 Log.e() 消息是以正常颜色书写的。

所以,这就是 logcat 报告的内容

5 .../W/System.err﹕ Unable to convert a [text/plain,UTF-8] representation into an object of class java.lang.String
5 .../W/System.err﹕ [ 175  3749: 3749 W/System.err ]
    android.os.NetworkOnMainThreadException
5 .../W/System.err﹕ at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
5 .../W/System.err﹕ at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:158)
5 .../W/System.err﹕ at libcore.io.IoBridge.recvfrom(IoBridge.java:525)
5 .../W/System.err﹕ at java.nio.SocketChannelImpl.readImpl(SocketChannelImpl.java:305)
5 .../W/System.err﹕ at java.nio.SocketChannelImpl.read(SocketChannelImpl.java:267)
5 .../W/System.err﹕ at org.restlet.engine.io.ReadableSocketChannel.read(ReadableSocketChannel.java:82)
5 .../W/System.err﹕ at org.restlet.engine.connector.Connection$1.read(Connection.java:232)
5 .../W/System.err﹕ at org.restlet.engine.io.Buffer.fill(Buffer.java:395)
5 .../W/System.err﹕ at org.restlet.engine.io.ReadableBufferedChannel.onFill(ReadableBufferedChannel.java:157)
5 .../W/System.err﹕ at org.restlet.engine.io.Buffer.process(Buffer.java:601)
5 .../W/System.err﹕ at org.restlet.engine.io.ReadableBufferedChannel.read(ReadableBufferedChannel.java:176)
5 .../W/System.err﹕ at org.restlet.engine.io.Buffer.fill(Buffer.java:395)
5 .../W/System.err﹕ at org.restlet.engine.io.NbChannelInputStream.onFill(NbChannelInputStream.java:189)
5 .../W/System.err﹕ at org.restlet.engine.io.Buffer.process(Buffer.java:601)
5 .../W/System.err﹕ at org.restlet.engine.io.NbChannelInputStream.read(NbChannelInputStream.java:307)
5 .../W/System.err﹕ at java.io.InputStream.read(InputStream.java:163)
5 .../W/System.err﹕ at org.restlet.engine.io.BioUtils.copy(BioUtils.java:81)
5 .../W/System.err﹕ at org.restlet.engine.io.NioUtils.copy(NioUtils.java:148)
5 .../W/System.err﹕ at org.restlet.representation.ReadableRepresentation.write(ReadableRepresentation.java:104)
5 .../W/System.err﹕ at org.restlet.representation.ChannelRepresentation.write(ChannelRepresentation.java:76)
5 .../W/System.err﹕ at org.restlet.representation.ChannelRepresentation.write(ChannelRepresentation.java:82)
5 .../W/System.err﹕ at org.restlet.representation.Representation.getText(Representation.java:397)
9 .../W/System.err﹕ at org.restlet.engine.converter.DefaultConverter.toObject(DefaultConverter.java:260)
9 .../W/System.err﹕ at org.restlet.service.ConverterService.toObject(ConverterService.java:170)
9 .../W/System.err﹕ at org.restlet.resource.Resource.toObject(Resource.java:828)
9 .../W/System.err﹕ at org.restlet.engine.resource.ClientInvocationHandler.invoke(ClientInvocationHandler.java:240)
9 .../W/System.err﹕ at $Proxy23.getThreads(Native Method)
9 .../W/System.err﹕ at com.gmail.tigerjack89.pervasive.forum.SubforumContentActivity$LoadThreadsInBackground.loadThreads(SubforumContentActivity.java:329)
9 .../W/System.err﹕ at com.gmail.tigerjack89.pervasive.forum.SubforumContentActivity$LoadThreadsInBackground.access$400(SubforumContentActivity.java:283)
9 .../W/System.err﹕ at com.gmail.tigerjack89.pervasive.forum.SubforumContentActivity$LoadThreadsInBackground$1.run(SubforumContentActivity.java:301)
9 .../W/System.err﹕ at android.os.Handler.handleCallback(Handler.java:615)
9 .../W/System.err﹕ at android.os.Handler.dispatchMessage(Handler.java:92)
9 .../W/System.err﹕ at android.os.Looper.loop(Looper.java:137)
9 .../W/System.err﹕ at android.app.ActivityThread.main(ActivityThread.java:4745)
9 .../W/System.err﹕ at java.lang.reflect.Method.invokeNative(Native Method)
9 .../W/System.err﹕ at java.lang.reflect.Method.invoke(Method.java:511)
9 .../W/System.err﹕ at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
9 .../W/System.err﹕ at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
9 .../W/System.err﹕ at dalvik.system.NativeStart.main(Native Method)
    [ 187  3749: 3749 E/class com.gmail.tigerjack89.pervasive.forum.SubforumContentActivity$LoadThreadsInBackground NullPointerException
    java.lang.NullPointerException
            at com.fasterxml.jackson.core.JsonFactory.createParser(JsonFactory.java:822)
            at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2153)
            at com.gmail.tigerjack89.pervasive.forum.SubforumContentActivity$LoadThreadsInBackground.loadThreads(SubforumContentActivity.java:331)
            at com.gmail.tigerjack89.pervasive.forum.SubforumContentActivity$LoadThreadsInBackground.access$400(SubforumContentActivity.java:283)
            at com.gmail.tigerjack89.pervasive.forum.SubforumContentActivity$LoadThreadsInBackground$1.run(SubforumContentActivity.java:301)
            at android.os.Handler.handleCallback(Handler.java:615)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4745)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
            at dalvik.system.NativeStart.main(Native Method)

在最初的问题中,我忽略了我正在使用 Jackson 来序列化我的实体,因为似乎只是间接地参与了这个问题。我的意思是,它仅在 retrievedString 为 null 时引发 NullPointerException


AsyncTask代码

根据要求,这里有很多来 self 的 AsynkTask 的代码

  private class LoadThreadsInBackground extends LoadFromServerInBackground
  {
    public LoadThreadsInBackground()
    {
      super(SubforumContentActivity.this);
    }
    @Override
    protected Void doInBackground(final Boolean... params)
    {
      runOnUiThread(
        new Runnable()
        {
          @Override
          public void run()
          {
            currentThreadsPosition = threadsListView.getFirstVisiblePosition();

            // Appending new data to threadsList
            loadThreads(params[0]);

            // Setting new scroll position
            threadsListView.setSelectionFromTop(currentThreadsPosition + 1, 0);
          }
        });
      return (null);
    }

    private void loadThreads(boolean reload)
    {
      if (reload) threadList.clear();

      ClientResource cr = new ClientResource("IP address");
      cr.setChallengeResponse(getAuthentication());
      ThreadsInSubforumIdByPage tis = cr.wrap(ThreadsInSubforumIdByPage.class);

      List<Thread> retrievedList;
        String s = tis.getThreads();
        retrievedList =
          getObjectMapper().readValue(
            s, new TypeReference<List<Thread>>(){});
      threadList.addAll(retrievedList);

      if ((retrievedList == null) || (retrievedList.size() < Constants
        .RETRIEVED_PER_PAGE))
      {
        loadMoreThreadsButton.setEnabled(false);
        if (retrievedList != null && retrievedList.size() == 0)
        { currentThreadsPage--; }
      }
    }
  }

它扩展了这个抽象类

public abstract class LoadFromServerInBackground extends AsyncTask<Boolean, Void, Void>
{
  private ProgressDialog mProgressDialog;
  private Activity mInvokerActivity;

  public LoadFromServerInBackground(Activity invokerActivity)
  {
    mInvokerActivity = invokerActivity;
  }

  @Override
  protected void onPreExecute()
  {
    // Showing progress dialog before sending http request
    mProgressDialog = new ProgressDialog(mInvokerActivity);
    mProgressDialog.setMessage("Please wait ...");
    mProgressDialog.setIndeterminate(true);
    mProgressDialog.setCancelable(false);
    mProgressDialog.show();
  }

  @Override
  protected void onPostExecute(Void unused)
  {
    // closing progress dialog
    mProgressDialog.dismiss();
  }
}

最佳答案

您通过调用 runOnUiThread() 滥用了您的 AsyncTaskrunOnUiThread() 完全如其所说:在 UI 线程上执行 Runnable 中的代码。

Android 上的网络通信必须在后台线程上执行,runOnUiThread() 打破了这一要求。

试试这个版本的AsyncTask:

    private class LoadThreadsInBackground extends LoadFromServerInBackground<List<Thread>> {
    int currentThreadsPosition;
    boolean reload;

    public LoadThreadsInBackground() {
        super(SubforumContentActivity.this);
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        currentThreadsPosition = threadsListView.getFirstVisiblePosition();
    }

    @Override
    protected List<Thread> doInBackground(final Boolean... params) {
        reload = params[0];
        // Load data from network
        return loadThreads();
    }

    @Override
    protected void onPostExecute(List<Thread> retrievedList) {
        super.onPostExecute(retrievedList);

        if (reload) {
            threadList.clear();
        }

        // Appending new data to threadsList
        threadList.addAll(retrievedList);

        if ((retrievedList == null) || (retrievedList.size() < Constants.RETRIEVED_PER_PAGE)) {
            loadMoreThreadsButton.setEnabled(false);
            if (retrievedList != null && retrievedList.size() == 0) {
                currentThreadsPage--; 
            }
        }

        threadsListView.setSelectionFromTop(currentThreadsPosition + 1, 0);
    }

    private List<Thread> loadThreads() {
        ClientResource cr = new ClientResource("IP address");
        cr.setChallengeResponse(getAuthentication());
        ThreadsInSubforumIdByPage tis = cr.wrap(ThreadsInSubforumIdByPage.class);

        String s = tis.getThreads();
        List<Thread> retrievedList = getObjectMapper().readValue(s, List<Thread>.class);
        return retrievedList;
    }
}

然后,让它扩展这个类:

public abstract class LoadFromServerInBackground<T> extends AsyncTask<Boolean, Void, T> {
    private ProgressDialog mProgressDialog;
    private Activity mInvokerActivity;

    public LoadFromServerInBackground(Activity invokerActivity) {
        mInvokerActivity = invokerActivity;
    }

    @Override
    protected void onPreExecute() {
        // Showing progress dialog before sending http request
        mProgressDialog = new ProgressDialog(mInvokerActivity);
        mProgressDialog.setMessage("Please wait ...");
        mProgressDialog.setIndeterminate(true);
        mProgressDialog.setCancelable(false);
        mProgressDialog.show();
    }

    @Override
    protected void onPostExecute(T unused) {
        // closing progress dialog
        mProgressDialog.dismiss();
    }
}

关于java - 无法将 [text/plain,UTF-8] 表示形式转换为类 java.lang.String 的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28149169/

相关文章:

android - Android录音的动态采样率

java - ReSTLet 版本 2.2 java.lang.NoSuchMethodError : javax/xml/stream/XMLInputFactory. newFactory()

tomcat - 在 tomcat 上部署基于 reSTLet 的应用程序的问题

java - Eclipse 和 J2ME 模拟器定制

java - Spring 3.2 中@MatrixVariable 注解的一些信息

java - Do While 循环第二次不与扫描仪协调

java - 如何在使用 TabHost 创建的 Android 中仅显示选定的选项卡布局

java - TextToSpeech SynthesizeToFile 何时完成?

configuration - ReSTLet - 提供静态内容

java - 线程是否需要处于 RUNNABLE 状态才能被中断?